Unable to convert uint8_t array to unsigned long in Arduino - c++

I am trying to convert uint8_t readData[10] = "123456789" ; to unsigned long to do some math on this value, in Arduino. I'm using strtoul function. strtoul works fine if I define above array by my self and it converts this array to unsigned long successfully. But if I put some values in this array by reading DS1307 NVRAM, then strtoul fails to convert the array into unsigned long and gives 0 answer. I checked values in readData array, after reading NVRAM, using for loop, and found that values are same that i have saved in the NVRAM.
I am using NodeMCU board along with DS1307. My code and its Output is given below.
// Example of using the non-volatile RAM storage on the DS1307.
// You can write up to 56 bytes from address 0 to 55.
// Data will be persisted as long as the DS1307 has battery power.
#include "RTClib.h"
RTC_DS1307 rtc;
uint8_t readData[9] = "0"; //**this will store integer values from DS1307 NVRAM.
unsigned long convertedL1 = 0; //this will store converted value
uint8_t savedData[10] = "123456789"; //I have already filled this array for testing strtoul function.
unsigned long convertedL2 = 0; //this will store converted value of savedData array
void setup () {
Serial.begin(9600);
delay(3000);
#ifndef ESP8266
while (!Serial); // wait for serial port to connect. Needed for native USB
#endif
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
delay(3000);
while(1);
}
rtc.readnvram(readData,9,2); //Read NVRAM from address 2 to 11.
delay(20);
Serial.println("Prinitng values( using loop) stored in readData array, after reading NVRAM :");
for (int i = 0; i <9; i++) {
Serial.print(readData[i]);
}
Serial.println();
//Converting both arrays of same type using stroul
convertedL1 = (unsigned long)strtoul((char *)&readData[0],NULL,10);
convertedL2 = (unsigned long)strtoul((char *)&savedData[0],NULL,10);
Serial.print("converted value of readData array = ");
Serial.println(convertedL1);
Serial.println();
Serial.print("converted value of savedData array = ");
Serial.println(convertedL2);
}//setup end
void loop () {
// Do nothing in the loop.
}
the Output on Serial Monitor is:
Prinitng values( using loop) stored in readData array, after reading NVRAM :
123456789
converted value of readData array = 0
converted value of savedData array = 123456789
Why strtoul function works with one array and not with other.I searched many forums but couldn't find any solution.
Can anyone, please have a look at my code and kindly suggest me the solution. Any help will be highly appreciated.

Seems likely the reason for the difference is that your savedData array is null terminated but your readData array is not. strtoul requires that the array be null terminated.
Change your code like this
uint8_t readData[10] = "0"; // one extra byte for null terminator
...
rtc.readnvram(readData,9,2); //Read NVRAM from address 2 to 11.
readData[9] = '\0'; // add the null terminator

Related

How to send data in hex on SerialPort

How to send data in hex on SerialPort?
I used this function, I receive the "yes, I can write to port" but I do not receive the data I entered
QByteArray send_data;
if(serialPort->isWritable())
{
qDebug()<<"Yes, I can write to port!";
int size = sizeof(send_data);
serialPort->write(send_data,size);
}
send_data += static_cast<char>(0xAA);
serialPort->write(send_data);
Data are transmitted in binary (essentially a sequence of 0 and 1). No matter what. Showing data in hexadecimal rather than a string of characters is just a choice.
In the following example, you can see that the array string_c is initialized with the same string that you are using in your code. Next, I print the data in both, as hex and as a string. You can see that the only difference is in the way I decided to print the data. The source data is the same for both.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
void printCharInHexadecimal(const char* str, int len)
{
for (int i = 0; i < len; ++ i) {
uint8_t val = str[i];
char tbl[] = "0123456789ABCDEF";
printf("0x");
printf("%c", tbl[val / 16]);
printf("%c", tbl[val % 16]);
printf(" ");
}
printf("\n");
}
int main()
{
char string_c[] = "Yes, i can write to port";
// string printed in hex
printCharInHexadecimal(string_c, 24);
// same string printed as "text"
printf("%s\n",string_c);
return 0;
}
You can see the above code running here: https://onlinegdb.com/Y7fwaMTDoq
Note: I got the function printCharInHexadecimal from here: https://helloacm.com/the-c-function-to-print-a-char-array-string-in-hexadecimal/
As suspected, your use of sizeof is wrong. It is not returning the size of the contained data, it is returning a non-zero constant that is the size of a QByteArray object itself. Since that object was freshly constructed it should be empty, and any size you use in the first write other than zero will lead to undefined behavior. Use:
int size = (int)send_data.size();
Skip the first write entirely, and use the above for your second write.
You need to be clear about what you expect. 0xAA in your source code is simply an integer value using hex representation. It complies to exactly the same code regardless of the source code presentation: 0xAA == 170 == 0263.
If you actually intended to output a string of characters at run time representing a value in hexadecimal, you need to convert that value from an integer to a string. For example;
char hexbyte[3] ;
sprintf( hexbyte, "%02X", 170 ) ;
serialPort->write(send_data) ;
will output ASCII characters AA, whilst demonstrating the equivalence of 170 to 0xAA. That is the hex notation in the source does not affect the value or how it is stored or represented in the compiled machine code.

How do I get my Arduino to stop sending jumbled Unicode instead of numbers?

I'm trying to collect data from a simple multimeter circuit, but instead of returning numbers my serial port is just outputting random Unicode symbols.
Here's my code:
void setup() {
pinMode(2, INPUT);
Serial.begin(1200);
int prevVal = 0;
int timeVar = 0;
}
void loop() {
int digisensorVal = digitalRead(2);
int anasensorVal = analogRead(2) * 100;
Serial.print("D" + digisensorVal);
Serial.print(",");
Serial.println("A" + anasensorVal);
delay(250);
}
And here's a sample of the output:
⸮L/⸮U⸮⸮⸮⸮⸮?⸮⸮⸮w⸮e⸮⸮⸮⸮1⸮⸮⸮⸮}⸮J⸮⸮⸮⸮⸮oޝ⸮Y⸮⸮⸮|s⸮⸮}⸮⸮⸮⸮⸮⸮⸮є6x⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮y[⸮⸮⸮⸮⸮?⸮v⸮=⸮⸮⸮-⸮^⸮Y_z⸮⸮d⸮⸮⸮%ܿjV⸮~O⸮⸮G⸮⸮⸮⸮e⸮⸮U⸮⸮~+0⸮⸮⸮hh⸮s⸮
⸮c⸮⸮⸮+⸮⸮io3:⸮5kλϣ
,⸮g⸮⸮⸮⸮⸮>⸮⸮
⸮yꨛ⸮v⸮N⸮⸮⸮=⸮⸮=⸮⸮⸮l⸮⸮g⸮g⸮⸮⸮⸮⸮s⸮U⸮⸮⸮⸮⸮⸮=⸮ܳt⸮⸮⸮}⸮⸮'⸮˾⸮k⸮⸮⸮⸮⸮⸮⸮{⸮ᦒ⸮⸮⸮⸮ϓ߿gVp⸮⸮⸮⸮Y⸮⸮O⸮/F⸮~⸮⸮⸮⸮q4⸮⸮_f⸮⸮⸮⸮⸮I|P⸮⸮⸮NE⸮~u⸮7⸮⸮⸮⸮g⸮⸮G~⸮⸮⸮⸮__#⸮⸮⸮⸮⸮⸮⸮C⸮⸮⸮k⸮T⸮o/⸮t^⸮~⸮{}⸮w⸮⸮⸮⸮'h=⸮ϸ~⸮⸮⸮⸮⸮⸮⸮?⸮s⸮s⸮l⸮o5⸮^⸮⸮⸮w9{]⸮⸮q~⸮⸮⸮,⸮⸮⸮c⸮2_⸮⸮⸮⸮o6k)ޏ⸮k⸮ׇ⸮i⸮⸮m⸮⸮:⸮⸮⸮⸮|⸮⸮??⸮⸮⸮⸮3⸮⸮⸮⸮⸮⸮⸮⸮⸮^⸮⸮ڏ⸮⸮⸮⸮l⸮⸮⸮⸮⸮⸮H⸮~⸮>⸮⸮z⸮⸮⸮⸮⸮OwM;⸮⸮l⸮⸮
⸮sr⸮S⸮⸮}⸮⸮⸮⸮ׂٶ⸮⸮~⸮{⸮⸮]⸮⸮⸮⸮⸮⸮⸮⸮i⸮⸮⸮⸮⸮[⸮⸮⸮⸮⸮Nz⸮⸮⸮⸮⸮k⸮⸮⸮⸮⸮g⸮k⸮⸮⸮i3ɵ⸮⸮~⸮⸮⸮⸮⸮]⸮2ϪWކ⸮i>⸮gu⸮⸮ӵ⸮?⸮̥⸮⸮m⸮⸮|⸮⸮⸮⸮Wɓ⸮⸮⸮[⸮⸮O㠑_⸮⸮⸮⸮⸮⸮⸮⸮⸮/⸮M⸮⸮_⸮⸮gwF⥷⸮⸮yn⸮P⸮⸮-⸮⸮⸮N⸮⸮⸮=⸮⸮⸮⸮⸮⸮⸮>J⸮}⸮⸮&⸮⸮⸮C⸮HG翎⸮/⸮⸮⸮⸮}⸮⸮⸮^⸮⸮,⸮)[⸮⸮⸮⸮⸮⸮У⸮⸮}⸮ޯ⸮⸮⸮⸮7⸮⸮⸮⸮ó⸮U:~⸮⸮ns⸮⸮z⸮⸮n⸮⸮G|޿ӳ꓊⸮⸮}⸮⸮L⸮~⸮⸮KI⸮⸮G⸮⸮⸮⸮⸮⸮ӏ⸮⸮⸮⸮u6⸮W⸮⸮⸮⸮Ӊ۾⸮⸮9⸮zVΆ럿⸮⸮⸮ۘ⸮⸮T⸮<⸮⸮⸮⸮⸮⸮⸮/⸮⸮⸮⸮xG~⸮V⸮⸮u+N⸮⸮ݫ⸮⸮⸮cv~⸮⸮⸮W⸮
Serial.println("A" + anasensorVal);
This needs to be done in two lines. You're adding the sensor value to a pointer value and sending whatever garbage is pointed to at the memory location that adds up to. And it definitely isn't what you want. This isn't Java. You can't just add strings with a + like that.
With
Serial.println("A" + anasensorVal);
you are not actually printing number, but a string from some place in the memory starting at the address of "A" + value of "anasensorVal" and thus you will get some garbage.
You are trying to add an integer to a pointer to char(and likely move beyond the end of the string "A"), that's not what you want.
The usual way of formating output on arduino:
Serial.print("A");
Serial.println(anasensorVal);
Alternatively, you can define a stream operator for the Serial object, see https://playground.arduino.cc/Main/StreamingOutput how to do that and then format output like this:
Serial << "A" << anasensorVal;
Adding an int type and character type in Serial.print is messing up the format of the data you are trying to print to the monitor.

How to convert a char array to a byte array?

I'm working on my project and now I'm stuck with a problem that is, how can I convert a char array to a byte array?.
For example: I need to convert char[9] "fff2bdf1" to a byte array that is byte[4] is 0xff,0xf2,0xbd,0xf1.
Here is a little Arduino sketch illustrating one way to do this:
void setup() {
Serial.begin(9600);
char arr[] = "abcdef98";
byte out[4];
auto getNum = [](char c){ return c > '9' ? c - 'a' + 10 : c - '0'; };
byte *ptr = out;
for(char *idx = arr ; *idx ; ++idx, ++ptr ){
*ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
}
//Check converted byte values.
for( byte b : out )
Serial.println( b, HEX );
}
void loop() {
}
The loop will keep converting until it hits a null character. Also the code used in getNumonly deals with lower case values. If you need to parse uppercase values its an easy change. If you need to parse both then its only a little more code, I'll leave that for you if needed (let me know if you cannot work it out and need it).
This will output to the serial monitor the 4 byte values contained in out after conversion.
AB
CD
EF
98
Edit: How to use different length inputs.
The loop does not care how much data there is, as long as there are an even number of inputs (two ascii chars for each byte of output) plus a single terminating null. It simply stops converting when it hits the input strings terminating null.
So to do a longer conversion in the sketch above, you only need to change the length of the output (to accommodate the longer number). I.e:
char arr[] = "abcdef9876543210";
byte out[8];
The 4 inside the loop doesn't change. It is shifting the first number into position.
For the first two inputs ("ab") the code first converts the 'a' to the number 10, or hexidecimal A. It then shifts it left 4 bits, so it resides in the upper four bits of the byte: 0A to A0. Then the second value B is simply added to the number giving AB.
Assuming you want to parse the hex values in your string, and two letters always make up one byte value (so you use leading zeros), you can use sscanf like this:
char input[] = "fff2bdf1";
unsigned char output[4];
for (int i=0; i<4; i++) {
sscanf(&input[i*2], "%02xd", &data[i]);
}
Just shift 0 or 1 to its position in binary format :)
char lineChars[8] = {1,1,0,0,0,1,0,1};
char lineChar = 0;
for(int i=0; i<8;i++)
{
lineChar |= lineChars[i] << (7-i);
}
Example 2. But is not tested!
void abs()
{
char* charData = new char;
*charData = 'h';
BYTE* byteData = new BYTE;
*byteData = *(BYTE*)charData;
}

Arduino unsigned long int to char*

I am coding on Attiny85 with IRremote and SSD1306 libraries customized.
When receiving IR data the results are stored this way:
unsigned long value // Decoded value, max 32 bits
volatile unsigned int *rawbuf // Raw interval in 50uS ticks
int rawlen // Number of records in rawbuf
OLED display related functions are:
void printChar (char ch)
void printString (char* pText)
I am struggling with printing the received IR value to the OLED SSD1306 screen. User is able to review and save the received code to EEPROM and hence I have tried all different conversions but I am unable to print the results.value to the screen in a way that it would display the received HEX code (for example 0xE0E040BF which is Power on in Samsung television).
Due to lag of Serial in attiny85 I have no clue how I could debug this and get it working. Any help?
EDIT (adding relative code):
#include "SSD1306.h"
#include "IRremote.h"
...
if (irrecv.decode(&results)) {
dumpCode(&results);
irsend.sendRaw(buff, results.rawlen, 38);
oled.printString("Received IR");
// Print received hexadecimal IR code to the OLED screen
irrecv.enableIRIn();
irrecv.resume();
}
If I understand it correctly you just want to convert a unsigned long value into an hex string, you can use sprintf for this purpose (ideone):
const unsigned int BUFFER_LENGTH = 16;
char buffer[BUFFER_LENGTH];
unsigned long value = 0xE0E040BF;
sprintf(buffer, "0x%08X", value);
printf("%s\n", buffer); // printString(buffer)
so that you can pass buffer to the printString method of the oled screen.
The format specifier %08X instructs printf to format the value as an hexadecimal number, with capital letters always showing all 8 hex values for the 4 bytes and padding it with 0s.
You could do this:
int IR;
char hexadec_s[11];
sprintf(hexadec_s,"0x%08x",IR);
printString(hexadec_s);
I believe this should do the trick. Let me know if it worked.

Arduino Integer error

We are trying to initialize a character array but it we get an error saying that we can not as we can not mix integers and chars, but we dont have have integers initialized.
thanks in advance
void setup()
{
Serial.begin(9600); //Set the serial monitor.
lcd.begin(16, 2); //Set the LCD
}
char line1 [5] = {0};
char line2 [] = {0};
void loop()
{
if (Serial.available() > 0) { //If the serial monitor is open it will read a value.
line1 = Serial.read();
delay(10);
Serial.print(line1);
lcd.print(line1);
}
}
I am not an arduino guy, but I did stay at a Holiday Inn last night with access to Google :)
http://arduino.cc/en/Serial/Read
Serial.read() returns a single byte (as an int). You're trying to assign that to a char array.
You can't do that. You can assign something to a specific element in an array:
line1[0] = 'c';
for example, but you can't assign to an array itself.
It seems like you're looking for Serial.readBytes()
http://arduino.cc/en/Serial/ReadBytes
Which would look like:
Serial.readBytes(line1, 5);
in your case where 5 is the length of your buffer (array). This would read (at most) 5 bytes into your line1 buffer.
Edit to add: That being said, it appears arduino's "C-Like" language is very much like C in that it expects "Strings" (char arrays) to be null terminated when passing them to Serial.print(). The advice above doesn't do that and in fact would cause problems.
What you would need to do is read up to one byte less than the length of your array, and then null terminate the "string" using the number of bytes actually read which is what bytesRead() returns to you (arrays are zero indexed):
int numBytesRead = 0;
...
numBytesRead = Serial.readBytes(line1, 4);
line1[numBytesRead] = '\0';
Serial.print(line1);
Option B is to do as I originally mentioned, but loop and print one byte at a time from your line1 array using the index:
int numBytesRead = 0;
numBytesRead = Serial.readBytes(line1, 5);
int i;
for (i = 0; i < numBytesRead; i++) {
Serial.print(line1[i]);
}
According to the docs Serial.print() automagically knows to send a single byte/char when that's all that's passed to it.