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.
Related
I would like to convert float values to IEEE754 Single precision 32-bit Hex values in the following site on Arduino.
https://www.binaryconvert.com/result_float.html?decimal=051046049048
float f = 3.10;
byte hex[4] = {0};
byte FloatToHex(float f){
.......
}
How can I create a function like this?
It's okay if the format is different.
f is already stored in binary. reinterpret_cast is generally a code smell issue, but its valid use is to view the byte representation of variables.
void FloatToHex(float f, byte* hex){
byte* f_byte = reinterpret_cast<byte*>(&f);
memcpy(hex, f_byte, 4);
}
void setup() {
float f = 3.10;
byte hex[4] = {0};
FloatToHex(f, hex);
//... do stuff with hex now...
}
void loop() {
}
On my NodeMCU V3 I get a string, convert it to two longs, one int and two bytes, save them in a union and send the whole union to an Arduino Mega, which is supposed to read it in an equal union.
When the NodeMCU prints the bytes to the serial monitor of my laptop it shows their exact value, but after sending them I just get two 0s. Still I think it has something to do with the conversion of the bytes but can't figure out what.
I tried:
Using atol instead of strtol for converting the string, but discarded that
after reading about the
disadvantages. atol() v/s. strtol()
It didn't work anyway.
I tried to convert the bytes with lowByte((int) int1).
Here is the relevant part of my code. I made up a string, instead of receiving one for test purposes.
#include <ESP8266WiFi.h>
union Serial { //Union to place the numbers in.
byte by[12];
struct {
long vsollneu;
long ssollneu;
int phisollneu;
byte priosollneu;
byte typsollneu;
} Befehlssammlung;
} Befehle;
long a1,pr1,ty1;
char str[]="2049714 -1927461000 17 80 4"; //String to be seperated
void convert(char*);
void setup(){
Serial.begin(9600);
}
void loop(){
convert(str);
//Serial.write(Befehle.by,12); //Send the Bytes of the Union to the Arduino MEGA
delay(5555);
}
void convert(char* str){ //Converting the String with strtol
char* ende;
Befehle.Befehlssammlung.vsollneu =strtol(str,&ende,10);
Befehle.Befehlssammlung.ssollneu =strtol(ende,&ende,10);
a1 = strtol(ende,&ende,10);
pr1= strtol(ende,&ende,10);
ty1= strtol(ende,NULL,10);
Befehle.Befehlssammlung.phisollneu=(int) a1; //Converting the long to an int
Befehle.Befehlssammlung.priosollneu=(byte) pr1; //Probably that's somehow wrong???
Befehle.Befehlssammlung.typsollneu=(byte) ty1;
// Serial.println(Befehle.Befehlssammlung.vsollneu);
// Serial.println(Befehle.Befehlssammlung.ssollneu);
// Serial.println(Befehle.Befehlssammlung.phisollneu);
// Serial.println(Befehle.Befehlssammlung.priosollneu);
// Serial.println(Befehle.Befehlssammlung.typsollneu);
}
Here is the receiving part of the Arduino Mega:
union IZweiCkontainer {
byte by[12];
struct {
long vsollneu;
long ssollneu ;
int phisollneu;
byte priosollneu;
byte typsollneu;
} Befehlssammlung;
} Befehle;
void setup(){
Serial.begin(115200); //Serial for debugging
Serial3.begin(9600); //Serial for conncetion the the Mcu
}
void loop(){
if(Serial3.available()>0){
while(Serial3.available()){
Serial3.readBytes(Befehle.by,12); //receiving the Bytes and writing them in the "same" union
}
}
Serial.println(Befehle.Befehlssammlung.vsollneu);
Serial.println(Befehle.Befehlssammlung.ssollneu);
Serial.println(Befehle.Befehlssammlung.phisollneu);
Serial.println(Befehle.Befehlssammlung.priosollneu);
Serial.println(Befehle.Befehlssammlung.typsollneu);
}
What bucks me is that everything is fine on the NodeMCU but after sending I get the following output from the Arduino Mega:
2049714
-1927461000
17
0
0
ints and longs on an Arduino and ESP8266 are not the same size.
Use int16_t and int32_t to make sure they are the same size across different architectures.
union {
byte by[12];
struct {
int32_t vsollneu;
int32_t ssollneu;
int16_t phisollneu;
byte priosollneu;
byte typsollneu;
} Befehlssammlung;
} Befehle;
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.
int i;
float number=123.456;
void setup()
{
Serial.begin(9600);
}
void loop()
{
byte a;
a=lowByte(number);
//is this the way i extract the right most byte from a 4 bytes float? equating a byte named a with the function lowByte? Is this how i use the lowByte function? cos i couldnt compile this in my arduino IDE.
delay(1000);
}
/*
what i am trying to do is to transmit float 123.456 over zigbee. and i believe data transmission is done byte by byte. so what i am trying to do is to break this float up into 4 bytes and send them byte by byte. how i do it is i intend to use lowbyte. then i just bitshfit by 8 bits (equivalent to 1 byte) to the right. then i use lowByte again. then again bitshift by 8 and lowByte and the repeat the process until i capture all 4 bytes.
so what i want to find out is how do i break the float into 4 bytes? and store these values for them to be sent?
can it be done in a byte array?
*/
I wanted to to the exact same thing and i found the below would work.
One approach is to use a union that stores the float value along with a unsigned char array. For example:
union v {
float f;
unsigned char uc[4];
};
union v val;
float f;
extern void store_byte (unsigned char v);
void test (void) {
val.f = 34.567; // set floating point value
store_byte (val.uc[0]); // write access to the bytes of the float value
store_byte (val.uc[1]);
store_byte (val.uc[2]);
store_byte (val.uc[3]);
val.uc[0] = 0x3F; // set float value (1.1)
val.uc[1] = 0x8C;
val.uc[2] = 0xCC;
val.uc[3] = 0xCD;
f = val.f; // read the value as FLOAT type.
}
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;
}
}
}