Data sent through serial on arduino gets byte-shifted sometimes - arduino

I'm sending data through USART on an Arduino Due. I'm currently filling a buffer so the data gets sent just when a buffer is full.
The data I'm putting into the buffer is a lookup table of different wave shapes with 12 bits of depth (values from 0 to 4095). So I'm putting into the buffer values that are 2 bytes of depth, and the most significant byte is always 0.
My problem is that everyonce in a while a whole wave period gets shifted a byte (every value gets multiplicated by 256). The error is unpredictable: it might happen on the 2nd or 3rd period to be sent, but it happens soon. I tried slower baudrates, or adding two stopbits, but nothing fixes it. The relevant chunk of the code:
const int buflen = 2048;
int i = 0;
int j = 0;
int k = 1;
int wave = 0;
short buff[buflen];
volatile PROGMEM short sintab[3][512] = ...//there's no need to paste here the lookup tables
void setup(void){
Serial3.begin(115200, SERIAL_8N2);
}
void loop(void) {
buff[j]= sintab[wave][i];
i+= k;
j++;
if (i>511){
i-=512;
}
if (j>=buflen){
byte* bytePointer =(byte*)buff;
for (int l=0; l<=buflen; l++){
Serial3.write(bytePointer[l]);
Serial3.flush();
}
int j = =0;
}
I'm checking the received data on both a serial monitor and a python program that stores the received values and print them. I think its weird that the error never happens in the middle of a wave: a one or two waves are copied good on the buffer and then a whole value gets shifted. How could I fix this?

It looks like the issue is not in this block of code where you're writing the data out to your USART port, rather in storing the data to that array. When you have this byte offset occur, can you validate that the data in your array is as you expect it to be?
Edit:
Change
for (int l=0; l<=buflen; l++)
to
for (int l=0; l< buflen; l++)
so you enumerate over the set 0 to 511, which is 512 elements. Now you are enumerating an additional element, which is reading data from an unexpected memory location and returning whatever is there (likely the next byte of your static structure).

Related

Arduino - sending large amount of data over Serial

I am trying to build a simple FLASH memory programmer (for 39SF020A) using my arduino mega. I wrote the C code and Python script to send the data over (And it all works as expected).
I need to transfer about 32k of hexadecimal data, but with my settings only 10k of data took about 4 minutes (115200 BAUD), which i found unnecessary long. Currently, i am sending over serial (from Python) my value with a terminator (i chose '$'), so for exmple '3F$'. adresses are calulated on the arduino, so no need to send them.
In my arduino code, i have
String received_string = Serial.readStringUntil('$');
and after programming every byte to teh FLASH using arduino, it sends back a '\n' to let the Python know, that it is ready to receive next byte (the python is waiting for receiving a 'line' and then continues). I am not really sure if this is a way to do it, if sending only one byte at the time is good idea and if not, how many and how do i parse them on the arduino? Is the feedback loop useful?
Thanks.
Python Code:
('file' contains all data)
for item in file[1:]:
ser.write((item + "$").encode("ascii"))
line = ser.readline()
i += 1
if i >= top:
break
elif (i % 100) == 0:
print(i)
Arduino code (just part of it)
if (Serial.available() > 0){
String received_string = Serial.readStringUntil('$');
programData(received_string.toInt(),program_adress);
program_adress++;
}
void programData(char data_in, unsigned long adress)
{
digitalWrite(OE,HIGH);
digitalWrite(CE,LOW);
writeByte(0xAA, 0x5555);
writeByte(0x55, 0x2AAA);
writeByte(0xA0, 0x5555);
writeByte(data_in, adress);
Serial.print("\n"); // Feedback for Python
delayMicroseconds(30); // Just to be on the safe side
}
void writeByte(char data_in, unsigned long adress)
{
setDataAs(OUTPUT);
digitalWrite(OE,HIGH);
digitalWrite(WE,HIGH);
setAdress(adress);
setData(data_in);
digitalWrite(WE,LOW);
delayMicroseconds(1);
digitalWrite(WE,HIGH);
}
// Sets data BUS to input or output
void setDataAs(char dir){
for (unsigned int i = 0; i < data_size ;i++) pinMode(data[i],dir);
}
// Sets data to specific values
void setData(char data_i){
setDataAs(OUTPUT);
for (int i = 0; i < data_size;i++) { digitalWrite(data[i],bitRead(data_i,i)); }
}
void setAdress(long adr){
// Set all adresses
for (int i = 0; i < adresses_size;i++)
digitalWrite(adresses[i],bitRead(adr,i));
}

Trouble receiving radiopacaket from Lora radio

I am not able to receive the sent radio packet from the Lora rf95 transceiver.
I have tried declaring the received array as a char, uint8_t along with using len as size, however the size is 7 so i thought what I did was ok. It didn't recieve anything when I used:
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf95.recv(buf, &len))
{
digitalWrite(LED, HIGH);
RH_RF95::printBuffer("Received: ", buf, len);
Serial.print("Got: ");
Serial.println((char*)buf);}
It does receive something at the same rate as the transceiver when I use:
uint8_t P;
if(rf95.recv((uint8_t*)P,7)){
Serial.print((char)P);
Serial.println();
It prints the new line but no data. It was working before but when I started to try to adjust the power it no longer worked so I tried other things. I a new to coding so please don't be mean, I appreciate any help you can give.
You are converting a uint8_t to a uint8_t* this means that your uninitalized variable will be used to point to the location where rf95.recv is going to start storing its data. This means that if P = 5 it will start at memory location 5 and if P = 0 it will result in a null pointer.
What you should be doing is taking the address of P: rf95.recv(&P,7)).
As such these lines should be:
rf95.recv(&buf, &len)
RH_RF95::printBuffer("Received: ", &buf, len);
Serial.println(buf[0]);
or even better:
for(uint8_t i = 0; i<len; ++i) {
Serial.println(buf[i]);
}
Your second code block wasn't printing out any data because P was uninitialized and probably containing the value 0. So your received data was stored at address 0 instead of the address of the variable and as such wasn't changed by your receive because of the first pointer problem.

Unable to understand Raw IR Code

I am working on an IR based remote control app using arduino. After a long exploration i found few Raw Ir codes, which looks like -
"IR": "40064,1,1,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1057,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1057,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,5128"
enter code here
And it's very sad that even after getting this code i am unable to understand this code, I am using this aruino library - https://github.com/z3t0/Arduino-IRremote
where for sending raw codes is like this -
void IRsend::sendRaw (const unsigned int buf[], unsigned int len, unsigned int hz){
// Set IR carrier frequency
enableIROut(hz);
for (unsigned int i = 0; i < len; i++) {
if (i & 1) space(buf[i]) ;
else mark (buf[i]) ;
}
space(0); // Always end with the LED off
}
Where buf is an array containing intervals in microseconds during which signal will be low or high.
But the IR code i got above isn't working, because i think it's not having the time intervals but something else. Any lead would be gracious.

Infra Red Arduino Custom Serial

Basically I am looking to make an serial-like system that runs communication between IR LEDs on an arduino. Below the code gets to the point having an array with a collection of 1s and 0s in it. I need to convert this 8 bit array into a single character and output it. But I don't know how to do this. Help would be appreciated.
int IR_serial_read(){
int output_val;
int current_byte[7];
int counter = 0;
IR_serial_port = digitalRead(4);
if (IR_serial_port == HIGH){
output_val =1;
}
if (IR_serial_port == LOW){
output_val =0;
}
current_byte[counter] = output_val;
counter +=1
}
This would best be done with bitwise operators, I think the or function would be of best use here as it will set a bit if the input is 1 and not change it if it is 0, could use a loop to loop through your array and set the bits.
Looking at your code, are you sure you are receiving all 8 bits? You seem to be saving 7 bits.
As you are creating a byte array solely for the purpose of using only 1s and 0s, it suggest immediately setting the bits in the same loop.
Here is the code that I suggest:
byte inputByte = 0; // Result from IR transfer. Bits are set progressively.
for (byte bit = 0; bit < 8; bit++) { // Read the IR receiver once for each bit in the byte
byte mask = digitalRead(4); // digitalRead returns 1 or 0 for HIGH and LOW
mask <<= bit; // Shift that 1 or 0 into the bit of the byte we are on
inputByte |= mask; // Set the bit of the byte depending on receive
}
This would also be put inside a loop to read all the bytes in your data stream.
It is designed for readability and can be optimised further. It reads the least significant bit first.
You can also apply the same technique to your array if you wish to keep using an array of bytes just for 1s and 0s, just replace the digitalRead with the array location (current_byte[bit]).

How to print out a set of variables in a for loop

I'm writing a program that logs and prints digital and analog inputs. Unfortunately, the arduino is running out of memory. To make the program smaller I'm trying to print the inputs using a for loop. I've been trying to do:
for(int analog = analog0; analog <= analog9; analog ++){
Serial.println(analog);
}
When I run the arduino, it doesn't always print out all of the inputs, sometimes it prints out none, or one or two, up to around 16 inputs (I only have 10 wired up). Each time this loop runs, it prints a different amount of inputs. Any suggestions?
I don't know anything about arduino, but if analog0 is a reading of a analog value, then of course this code is not going to work. The value of analog is going to be a random ADC value! Perhaps you need to do
for(int i = 0; i<= 9; i++){
Serial.println(analogRead(i));
}
First of all your for loop is incorrectly coded.
Also, try storing the analog ints outside of loop():
int analog[10];
// etc.
loop() {
int x;
analog[0] = analogRead(analogPin0);
analog[1] = analogRead(analogPin1);
// etc. do calcs
// for a beginning programmer, this for loop is OK
for (idx = 0; idx < 10; idx++) {
serial.println(analog[idx]);
}
}

Resources