Arduino: string to multiple variables - arrays

I'm trying to send the data from two sensors through 433MHz radio communication. I have succeeded in sending and receiving the string(array of char) "number1,number2".
Now I'm trying to store both numbers in separate int variables (the values are over 256).
I've tried with almost everything (sscanf and atoi mainly), but it does not seem to work.
To A0 and A1 I have connected two potentiometers, whose values I want to store in valorX and valorY in the receiver arduino.
What do you suggest?
I cannot assure I used correctly sscanf and atoi.
Transmitter code:
#include <VirtualWire.h>
int xvalue;
int yvalue;
void setup() {
Serial.begin(9600);
vw_set_ptt_inverted(true); //
vw_set_tx_pin(12);
vw_setup(4000);// speed of data transfer Kbps
}
void loop() {
xvalue=analogRead(A0);
yvalue=analogRead(A1);
int envioX = map(xvalue, 0, 1023, 001, 1000); //I prefer to not send 0
int envioY = map(yvalue, 0, 1023, 001, 1000);
//Mando los datos del joystic
char envioXY[]="";
sprintf(envioXY,"%d,%d",envioX,envioY);
EnviarDatos(envioXY);
delay(1000);
}
void EnviarDatos(char datos[]){
vw_send((uint8_t *)datos, strlen(datos)); //vw_send(message, length)
vw_wait_tx(); // Wait until the whole message is gone
}
Receiver code:
#include <VirtualWire.h>
char recibo[8]="";
int valorX;
int valorY;
void setup(){
vw_set_ptt_inverted(true); // Required for DR3100
vw_set_rx_pin(12);
vw_setup(4000); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
Serial.begin(9600);
Serial.println("setup");
}
void loop(){
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)){ //check to see if anything has been received
for(int i=0;i<buflen;i++){
recibo[i]=char(buf[i]);
Serial.print(recibo[i]);
}
recibo[buflen]=NULL;
//String str(recibo);
//What here to get both int??
}
}
What do you suggest?
I cannot assure I used correctly sscanf and atoi.
So the main question is how to convert "number1,number2" to int1=number1 and int2=number2.
Thanks and cheers
Gabriel

Transmitter code:
You must declare storage for the sprintf to use. You have only declared a 1-byte array which contains a NUL (0 byte) as the first and only element [0]:
char envioXY[]="";
Change it to this, which declares a character array with 24 elements:
char envioXY[ 24 ];
Although uninitialized, sprintf will set the array elements as it formats your 2 integers.
Receiver code:
After recibo[buflen] = NULL;, you can parse it with this:
sscanf( recibo, "%d,%d", &valorX, &valorY );
The format string matches the sprintf format, and the address of the two integers is passed in, not just the two integers.

Related

Why my arduino serial to LCD gets stuck after 26 loop?

I get a float from raspberry pi (via struct module) and my sketch only shows the data on an LCD screen.
After 26 corrects loop, on the 27th, the Arduino crashes.
Can you tell me what's wrong with the 27th?
Changing delay from 20ms to 1s: NOK
Put the byte pointer out of the function: NOK
float f;
void getFloat(){
byte *fdata = (byte *) &f;
while(Serial.available() <= 4){}
Serial.readBytes(fdata,4);
}
void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 0);
lcd.print("Ready to receive");
getFloat();
AZ=f;
getFloat();
AL=f;
lcd.setCursor(0, 0);
lcd.print("Moving ");
lcd.setCursor(0, 1);
// print the number of seconds since reset:
lcd.print("AZ");
lcd.print(String(AZ));
lcd.setCursor(7, 1);
lcd.print("; AL");
lcd.print(String(AL));
delay(1000);
Serial.println("ok");
}
At the 27th, the arduino no longer acknoledge the data and the LCD shows :
==ving
AZy ; AL0.00=
=== Resolution ===
Before, I have to send twice the floats via the next code to get the last if not, I get the previous data on my arduino but i think the limitation comes from there :
def sendFloatToArduino(self,data):
self.serial.write(struct.pack('<f', data))
self.serial.flush()
def pointer(self,AZ,AL):
#send the data
print("AZ : "+str(AZ)+" ; AL : "+str(AL))
self.sendFloatToArduino(AZ)
self.sendFloatToArduino(AL)
self.sendFloatToArduino(AZ)
self.sendFloatToArduino(AL)
#wait for ack
while (self.serialArduino.in_waiting==0):
pass
print(self.serialArduino.readline())
After deleting the double sending, everything is fine.
Thanks for your answers.
The problem is not about the parsing as you said but with the LCD display.
I've tried converting floats to array and geting only 16 characters:
char str[16];
AZ=getFloat();
AL=getFloat();
char buffer1[20];
char buffer2[20];
dtostrf(AZ,7,5,buffer1);
dtostrf(AL,7,5,buffer2);
for (int i=0;i<8;i++){
if (i>1){
str[i]=buffer1[i-2];
str[i+8]=buffer2[i-2];
}
}
Serial.println(str);
But I get this on serial output : AZ358.54AL48.544\x12.BBHE\xb3CGm=\r\n => fixed with \0
I think the problem is elswhere : I have to send twice the floats via the next code to get the last if not, I get the previous data on my arduino but i think the limitation comes from there :
def sendFloatToArduino(self,data):
self.serial.write(struct.pack('<f', data))
self.serial.flush()
def pointer(self,AZ,AL):
#send the data
print("AZ : "+str(AZ)+" ; AL : "+str(AL))
self.sendFloatToArduino(AZ)
self.sendFloatToArduino(AL)
self.sendFloatToArduino(AZ)
self.sendFloatToArduino(AL)
#wait for ack
while (self.serialArduino.in_waiting==0):
pass
print(self.serialArduino.readline())
I can't figure out the problem, but you can try the following code. It's stronger I think.
float getFloat()
{
float res;
while (Serial.available() < sizeof(res))
;
Serial.readBytes((char*)&res, sizeof(res));
return res;
}
void loop()
{
// ...
AZ = getFloat();
AL = getFloat();
// ...
}

Sending decimals using radio.write(); with Arduino

I'm adapting a sketch I found to send sensor data over a wifi chip (Nrf2401), and although I get the message through, the value I send contains decimals (e.g. 24.59), but the received message will only be 24.
I'm sure there's something wrong on the transmitter part of the code, but I can't see what.
Here's my code:
#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>
OneWire oneWire(4);
DallasTemperature sensors(&oneWire);
// ce,csn pins
RF24 radio(8,7);
unsigned char data[3] = {
0};
unsigned long count=0;
void setup(void)
{
sensors.begin();
Serial.begin(57600);
Serial.println("**************V1 Send Sensor Data***********");
radio.begin();
radio.setPALevel(RF24_PA_LOW);
radio.setChannel(0x4c);
// open pipe for writing
radio.openWritingPipe(0xF0F0F0F0E1LL);
radio.enableDynamicPayloads();
radio.setAutoAck(true);
radio.powerUp();
Serial.println("...Sending");
}
void loop(void)
{
sensors.requestTemperatures();
float currentTemp;
currentTemp = sensors.getTempCByIndex(0);
//assign 'T' to represent a Temperature reading
data[0] = 'T';
data[1] = currentTemp;
count++;
// print and increment the counter
radio.write(data, sizeof(float)+1);
Serial.print("Temperature sent: ");
Serial.println(currentTemp);
// pause a second
delay(500);
}
In this example, when I print currentTemp, it will display the decimals, but if I print data[1], it won't.
What am I missing?
You are assigning data [1] = currentTemp. Current temp is a float, not a character so this won't work. Decimals are lost because the float will be cast to a char in the assignment. Make data into a larger buffer and use sprintf to print currentTemp if you want to use it as a string. Really you should be writing just currentTemp to the radio and formatting on the other end, which will make the operation faster and require less bandwith to transmit (not to mention that transmitting and formatting are different concerns and should be separated, not coupled, when possible).

C char array address issue

I am having a problem in C with addressing char array in a structure. When I write characters in the array it writes them in word boundaries and not character boundaries. Here is the structure declaration.
typedef struct RxBuffer {
int Status;
int ByteCount;
int Index;
char Data[SCI_BUFFER_LENGTH];
} RxBuffer;
and here is the code that actually does the write,
RxBuffer SciaRxBuffer;
char SciaRxData;
int LoopBackCrFlag;
int RxDataReady;
interrupt void scia_rx_isr()
{
// Get Rx Data and first LoopBack
SciaRxData = SciaRegs.SCIRXBUF.all; // Read data
SciaRegs.SCITXBUF = SciaRxData; // Send loop back Tx data
// Check to see if carriage return
if (SciaRxData == CR)
{
// Set the loopback flag so Line-feed is transmitted
LoopBackCrFlag = TRUE;
}
//!
//! Problem is right here. SciaRxData is being written into
//! SciaRxBuffer.Data[SciaRxBuffer.ByteCount++] on Word
//! boundaries instead of byte boundaries.
//!
// Stuff RxBuffer & Mark as busy
SciaRxBuffer.Data[SciaRxBuffer.ByteCount++] = SciaRxData;
SciaRxBuffer.Status = RX_BUSY;
if (SciaRxData == CR)
{
SciaRxBuffer.Status = RX_READY;
SciaRxBuffer.Index = 0;
RxDataReady = TRUE;
}
// Clear Overflow and interrupt flags
SciaRegs.SCIFFRX.bit.RXFFOVRCLR = 1; // Clear Overflow flag
SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1; // Clear Interrupt flag
// Issue the PIE ack
PieCtrlRegs.PIEACK.all|=0x100;
}
Any help is welcome
Best Regards,
Steve Mansfield
Thank you for everyone's input. I just did some digging into the hardware and found out that the TI DSP that I am using does not support byte operations. It's smallest operation is a word (2 bytes). Even though I declared the array as a char array, when I write to the array it writes it as an integer. If I want to handle byte operations I will have to shift left the first character 8 bits and then OR the next character and then write it into the array. Like everyone always says, if there is a problem with the hardware -- fix it in software!
Best Regards,
Steve Mansfield

How to receive int array from client side (written in C) to server (written in python)

I just want to send an array adc_array=[w, x, y, z] from client to server. Below is the client side code whereas my server is in python which accepts json only. I get no error when i compile the code however get 2 warnings :
1- warning: pointer targets in passing argument 2 of 'UDPWrite' differ in signedness.
2- warning: no newline at end of file.
But at the server side, i am not able to receive the whole array, instead i just get the first character of the array i.e. [ .
I am new to C programming. I would really appreciate any help.
// Main function
void FlyportTask()
{
// Flyport connects to default network
WFConnect(WF_DEFAULT);
while(WFGetStat() != CONNECTED);
vTaskDelay(25);
UARTWrite(1,"Flyport Wi-fi connected...hello world!\r\n");
BOOL UdpSocketOpenRequest=TRUE;
BYTE UdpSocket=0;
// openinging UDP socket
if (UdpSocketOpenRequest) //open socket
{
UdpSocketOpenRequest=FALSE;
if (UdpSocket!=0) //if this is not equals to zero
{
UDPClientClose(UdpSocket);
}
UARTWrite(1,"OpenSocket\r\n");
UdpSocket= UDPClientOpen("10.0.0.106", "8000"); //Client socket opening
}
while(1)
{
//defining pointer
int *array_pointer;
int adc_array[4];
int j;
char buf[10]; //buffer to print
// I have made a separate function to get adc values which returns the pointer to the array.
array_pointer = get_adcval();
UARTWrite (1, "ADC Array\r\n");
for (j = 0; j < 4; j++)
{
adc_array[j] = *(array_pointer + j);
sprintf (buf, "%d", adc_array[j]);
UARTWrite (1, buf);
UARTWrite (1, "\n");
}
//if UDP socket is open, send the data
if ((UdpSocket!=0))
{
// defining pointer of serial_out
char *s_out;
int size;
// creating a JSON array from adc_array with 4 elements
cJSON * int_array = cJSON_CreateIntArray(adc_array,4);
// Serializing the array
s_out = cJSON_Print(int_array);
//Writing to the serial output/monitor
UARTWrite(1, "\r\narray to be sent\r\n");
UARTWrite(1, s_out);
UARTWrite(1,"\r\n");
// Assume adc_array=[1021, 1022, 1023, 1024]
// I get output [1021, 1022, 1023, 1024]
//compose message
size = strlen(s_out);
UDPWrite (UdpSocket, s_out, size);
// at the server side, i just receive only first character i.e. [
/*to free the memory */
free(s_out);
}
//
// remember to add delay vTaskDelay(50) 50ms
//remember to close the socket
}
}
You didn't allocated memory for s_out. even if it is printing correct result on UART but still it can be overwritten by any of the UARTWrite functions or strlen() function in the next lines. If it is overwritten then the "size" variable will get the number of bytes starting from the first byte to first null character in the memory (this is how strlen() functions). hence the "size" value can be totally random. it can be 0 or 1 or 1000. if the size is not correct then you will receive only "size" number of bytes. In your case it is possible that size is one. try printing size before UDPWrite. fix this problem by adding a malloc call before serializing the array.
If it doesn't work either then check your receiver side. is your receiver working fine if you send some dummy data from a tested python client (or any other tested or reliable client)? if no then there is some problem with your receiver.
Print out what strlen(s_out) returns, also print out the return value of UDPWrite ( I assume that like any write function this will be returning the size of the data which is written to the socket).
By reading the function names I presume you are using UDP transmission which is unreliable.

Arduino conversions in C

void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
Serial.println();
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
//I tried something like this
//void time(){
//char* hr = (char*)hour();
//Serial.println(hr);
//}
//But when I print it it gives a whole bunch of jibberish
Here are the two functions I'm using what I'm trying to do is make a function like the digitalClockDisplay function but one that returns the hour:minute as a char* once I have that I want to be able to compare that to another char*
hour() seems to be returning a int, so
char* hr = (char*)hour();
Serial.println(hr);
casts a int to a pointer and then sends the bytes at that (meaningless) address to Serial.
You probably want something like:
char hr[8];
snprintf(hr,8,"%i:%02i",hour(),minute());
Serial.println(hr);

Resources