I'm using ArduinoJSON to write a couple of data points to my EEPROM on Arduino Uno. I'm running into a problem with getGroundedPR where I need to convert a uint8_t to a char to pass retrieved data into my JSON parser.
This is my first time using EEPROM so I'm willing to bet there's a better way to do this. Should I continue to use JSON or is there a better way? I'm being cautious of the 10k write limit (give or take) on the EEPROM.
the EEPROM read/write is commented out until I have my process nailed down
void IMUController::setGroundedPR(double p, double r) {
Serial.print("Setting IMU ground: ");
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["pitch"] = p;
root["roll"] = r;
root.printTo(Serial);
char buffer[256];
root.printTo(buffer, sizeof(buffer));
Serial.println();
// EEPROM.write(EEPROM_ADDRESS_IMU_GROUNDED, buffer);
}
double* IMUController::getGroundedPR() {
double ret[2] = {0, 0};
StaticJsonBuffer<200> jsonBuffer;
uint8_t json_saved = EEPROM.read(EEPROM_ADDRESS_IMU_GROUNDED);
char json[] = "asdf"; // convert json_saved to char here
JsonObject& root = jsonBuffer.parseObject(json);
if(!root.success()) {
// return the result
ret[0] = (double)root["pitch"];
ret[1] = (double)root["roll"];
return ret;
}
return ret;
}
The EEPROM functions read() and write() only deal with a single character. You need to use put() and get() to deal with arrays.
char buffer[256];
root.printTo(buffer, sizeof(buffer));
EEPROM.put(EEPROM_ADDRESS_IMU_GROUNDED, buffer);
And to read it back:
char json[256];
EEPROM.get(EEPROM_ADDRESS_IMU_GROUNDED, json);
JsonObject& root = jsonBuffer.parseObject(json);
You need to take care with he array sizes though, the EEPROM functions will get and put the number of bytes in the array (256). The string should be null terminated so the extra bytes shouldn't cause a problem.
Related
I have the following Arduino function:
void SendCommandToDisplay(byte message[], byte size)
{
byte header[] = {0x5A, 0xA5};
byte result[] = {};
memcpy(result, header, sizeof(header));
memcpy(result+sizeof(header), message, size);
for (byte i=0; i<sizeof(result); i++)
{
Serial.print(result[i], HEX);
Serial.print(' ');
}
}
Then I call this function as follows:
byte test[]={0x82, 0x20, 0x10, 0x00, 0x03};
SendCommandToDisplay(test, sizeof(test) / sizeof(byte));
And seems is not working, I'm doing something wrong or maybe I have to do a reference or pointer. Any clue?
You are not allocating memory for the result variable - in your case try this:
void SendCommandToDisplay(byte message[], byte size)
{
byte header[] = {0x5A, 0xA5};
byte result[sizeof(header)+size];
memcpy(result, header, sizeof(header));
memcpy(result+sizeof(header), message, size);
for (byte i=0; i<sizeof(result); i++)
{
Serial.print(result[i], HEX);
Serial.print(' ');
}
}
Once simple approach to inserting the byte count (of message) following header is to change how the header is initialized:
byte header[] = {0x5A, 0xA5, size};
Note: a prior edit added an alternative to use the sizeof(message) but that was incorrect and removed - sizeof(message) where message is a parameter returns the sizeof of a pointer which is 2 on an arduino.
So in my arduino programm I am working with char arrays in a function. I try to save them globally, but no matter how I do it, the global arrays contain only part of the original array and a ton of gibberish symbols.
char* naam;
char* compliment;
byte color = 0;
void setup() {
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
doStuff();
Serial.println(naam);
Serial.println(compliment);
Serial.println(color);
}
void loop() {
// put your main code here, to run repeatedly:
}
void doStuff(){
String raw = "1234567890123456,abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz,0";
int i = raw.indexOf(",");
int j = raw.indexOf(",", i+1);
char a[i+1];
char b[j-i];
raw.substring(0,i).toCharArray(naam, i+1);
raw.substring(i+1,j).toCharArray(compliment, j);
color = (byte) raw.substring(j+2,j+3).toInt();
Serial.println(a);
Serial.println(b);
naam = a;
compliment = b;
}
Can anyone explain to me why this does not work and point me in the right direction?
Here you create two char arrays a and b
char a[i+1];
char b[j-i];
You never assign any values to its elements befor you print them.
Hence you'll print whatever garbage is in those memory locations
Response to comment:
They are filled by the "toCharArray(compliment, j);". The println(a)
prints correctly
When you first call doStuff
You create two uninitialized char arrays a and b.
Then you store two substrings as char array to naam and compliment. Both uninitialized char pointers. So you're basically storing stuff in a random position in memory.
Then you print a and b which contain random garbage.
Then you store the addresses in a and b to naam and compliment.
Once doStuff returns a and b are out of scope. naam and compliment still point at their position but that memory is free to be used by something else.
I am using the Arduino IDE to to write a sketch that passes data saved in progmem to a function, the function then writes the progmem data to local array.
The code is below:
const uint8_t Data_3 [256] PROGMEM = {0x11, 0x39.....}
void setup() {
Serial.begin(57600);
Data(Data_3, 0x00, 256);
}
void loop() {
}
void Data(const uint8_t *data, uint8_t bank, uint16_t bytes) {
uint8_t buff1 [256];
buff1[0] = data[0];
Serial.println(buff1[0],HEX); // <--Works fine prints the correct value
for ( uint16_t x = 0; x < bytes + 1; x++ ) {
buff1[x] = data[x];
Serial.println(buff1[x],HEX); // <--Just prints garbage
}
}
When I assign buff1[0] = data[0] and print the result the answer is correct. When I loop a print function with buff1[x] = data[x] I just get rubbish. Does anyone know the reason for this?
You have to use #include <avr/pgmspace.h> and Serial.print(pgm_read_byte(data+x)); otherwise it'll try to get data from the same address but from RAM, not from Flash memory.
Or copy into the buffer by memcpy_P(buff, data, bytes);
I'm attempting to send 8-bit byteArrays to an rfduino.
In the sketch, I got
void RFduinoBLE_onReceive(char *data, int len) {
int firstbyte = data[0];
Serial.println(firstbyte)
}
This works fine if the firstbyte is over 32. But if I'm sending a byteArray of [13, ...], firstbyte is parsed as 0.
I think I understand why (?):
RFduinoBLE parses incoming data as characters before sending it to this function, and bytes up to 32 are empty string.
So my question is: how can I use the RFduinoBLE-onReceive to read bytearrays with values below 32?
The following seems to work just fine:
void RFduinoBLE_onReceive(char *data, int length) {
uint8_t firstbyte = data[0];
}
or for arrays
uint8_t getData[20];
void RFduinoBLE_onReceive(char *data, int length) {
for (i = 0; i < length; i++) {
getData[i] = data[i];
}
}
Not quite sure what went right/wrong where, but I suspect either using int firstbyte instead of uint8_t firstbyte or casting uint8_t firstbyte = (uint8_t) data[0] did something I didn't expect.
I've written the java code to send data to pic via serial port and now I need to program the microcontroller to read the data and make PortD.RD6=1 if the it receives 1 and PortD.RD6=0 if it receives 0. I've tried this code but I get many errors .
This is my first mikroC program so I really don't know how to manage these errors.
char output[1];
unsigned short i;
void main(){
TRISD = 0x01;
i = 0;
UART1_Init(9600);
while (1) {
if (UART1_Data_Ready()==1) {
i = UART1_Read(); // read the received data
ByteToStr(i, output);
if (output = "1" ) // this is where I get the error
{PortD.RD6=1;}
else { PortD.RD6=0;}
}}}
One error that I can spot is that ByteToStr returns three characters so it is probably overwriting other memory areas and giving an undefined result. You don't need to do that conversion you can simply read a byte into a char and do a comparison directly on that as follows:
void main()
{
char c;
TRISD = 0x01;
UART1_Init(9600);
while (1) {
if (UART1_Data_Ready()) {
c = UART1_Read();
if (c == '1')
PortD.RD6=1;
else
PortD.RD6=0;
}
}
}