I'm trying to transmit a char wirelessly and have the receiver read that char through serial in order to create a switch statement.
When trying to convert into int, I get the same int value no matter what char I type into the html text box. Serial.print(buffer); is displaying the right char. All help appreciated.
This is the char I'm inputting, and the result in the serial
Let's try this way. After convert "buffer" from "char"-->"int".You can check if h is digital or not before doing something.
//..Your code..//
//..Your code..//
//..Your code..//
int h = (int)buffer;
if (isDigit(h))
{
//Do something;
}
Related
I'm constantly sending structs of int64 via Pyserial with:
with serial.Serial(port='COM4', baudrate=115200, timeout=.1) as arduino:
value = write_read(struct.pack(">q", int_array[1][i])) #this sends signed int.64 in bytes
print(value)
the struct.pack has this shape, for example:
b'\xff\xff\xff\xff\xff\xff\xff\xef'
and the function write_read consists of:
def write_read(x):
arduino.write((x))
data = arduino.readline()
#the idea is to receive an ACK from the Arduino after 8 bytes (the full
#number)
return data
The code I'm trying to develop in arduino is the following:
void loop() {
// send data only when you receive data:
if (Serial.available() \> 0) {
// read the incoming byte:
incomingByte = Serial.read();
//read 8 bytes and create the result
r= function_to_read_8_last_bytes // or similar
// say what you got:
Serial.print("I received: ");
Serial.printlesultn(r, DEC);
Serial.write("ACK");
}
}
I'm very curious how I could do a robust "read 8 bytes" function.
Should I add some especial character in the Python part to indentify when it ends one value?
Thanks! I'll appreciate any help :)
Given the discussion in the comments, it's hard to receive a stream of bytes and be sure that the receiver is completely synchronized. However let's make some assumptions to ease the problem:
The serial buffer is empty when you connect your laptop to Arduino. This ensures you won't receive spurious data with no meaning. I had this problem happens a lot when the serial connection was ended abruptly by any cause.
You are not constantly sending bytes, Arduino has time to process them until the start of the new sequence.
You only send this data, so there is no need to create a higher level protocol on top of it. Bare in mind that the serial communication is almost just an hardware stack, you receive bytes with no headers.
For assumption 1 you can write a simple piece of code to consume all the spurious bytes in the serial buffer as soon as your main starts from Arudino, so this will be done everytime you connect the serial (as this is also where the power supply comes from). Something like this:
void serialFlush(){
while(Serial.available() > 0) {
char t = Serial.read();
}
}
You can send a "READY" signal back to the Python interface, so that the program knows you are ready to receive data.
Going on with the solution you can implement an easy CRC in python, an additional byte which contains a XOR of all the previous bytes, and you check that in Arduino upon reception complete.
def xor_reduce_long_int(li):
res = 0;
for i in range(8):
mask = (0xFF)<<(i*8)
print(hex(mask))
masked = (li&mask)>>(i*8)
res ^= masked
return res
with serial.Serial(port='COM4', baudrate=115200, timeout=.1) as arduino:
crc=xor_reduce_long_int(int_array[1][i])
value = write_read(struct.pack(">qc", int_array[1][i],crc)) #this sends signed int.64 in bytes
print(value)
And with Arduino I would read 8 bytes when they are available and put them into an unsigned char buffer. I would then define a union that alias such buffer to interpret it as long long int.
typedef struct long_int_CRC
{
union
{
unsigned char bytes[8];
long int data;
};
unsigned char CRC;
}data_T;
// .. Later in main
data_T = received_data;
int received_bytes=0
unsigned char my_CRC = 0;
unsigned char rec_byte= 0;
while( received_bytes < 8 )
{
if(Serial.available() )
{
// Get the byte
rec_byte = Serial.read()
// Store the byte and calc CRC
received_data.bytes[received_bytes] = rec_byte;
my_CRC ^= rec_byte;
// Increment counter for next byte
received_bytes++;
}
}
// Reception complete, check CRC
unsigned char rec_CRC;
if(Serial.available() )
{
rec_CRC = Serial.read()
}
if( my_CRC != rec_CRC )
{
// Something was wrong!
}
// Now access your data as a long int
Serial.print("I received: ");
Serial.printlesultn(received_data.data, DEC);
Serial.write("ACK");
I'm using an Arduino for a project that involves controlling a servo via the serial monitor. The Arduino was receiving different values than what I entered. I'm sure that this is because serial data is read as ASCII. Is there any way that I could convert it to Int? Thanks!
I assume by Arduino you mean "Arduino IDE (C++)".
Arduino has a toInt() function.
int asciiVal = 97;
String mystr = (char)asciiVal;
Serial.println(mystr); //prints a
Serial.println(mystr.toInt()); //prints 97
Explained here: https://www.arduino.cc/en/Tutorial/StringToIntExample
Do it like this:
string input = Serial.readString();
int angle = int(input);
As I answered here.
I am trying using the arduino IDE to write a sketch. I have data in progmem and want to move the data with a function to a memory address allocated using malloc. My code is below:
const uint8_t Data_6 [256] PROGMEM = { 0x11, 0x39......};
void setup() {
Serial.begin(57600);
oddBallData (Data_6, 0x00, 256);
}
void main() {
}
void oddBallData(const uint8_t *data, uint8_t mem, uint16_t bytes) {
uint8_t *buff1 = (uint8_t*)malloc(sizeof(bytes));
if (buff1 = 0) {
Serial.println(F("FATAL ERROR - NO MEMORY"));
}
else {
for (uint16_t x = 0; x < 6; x++ ) {
buff1[x] = data[x]; //edited from data[0] to [x] made a mistake in post
Serial.println(buff1[x],HEX);
}
}
buff1[0] = data[0];
Serial.println(buff1[0],HEX);
free(buff1);
}
I have some data saved in progmem and want to write that data to a second device using i2c protocol. I have multiple constant arrays of data saved to my progmem, with different sizes. So I have used malloc to reserve some memory from the heap, inside of the function.
I have not been able to write the data from the progmem so I have stripped things back to so that I am just trying to point to the progmem data using malloc and then print it.
This is where I found a the problem. If I print a single array entry from the data constant. It prints the correct value. If I use a loop I get mixed results, the loop works as long as the condition check value is below 3 or sometimes below 6!!!...?
If above this value the entire print is just garbage. Can anyone explain what I am seeing?
The culprit is probably
uint8_t *buff1 = (uint8_t*)malloc(sizeof(bytes));
sizeof(bytes) returns the size of the variable (which is probably 2 bytes) so you are just allocating 2 bytes of memory. You should use the value directly, eg:
uint8_t* buff1 = malloc(bytes);
Mind that the cast is not required in C since a void* is convertible to any other pointer type directly.
Again - AVR PROGMEM is not directly accessible from memory space, it needs different instruction than access into the RAM. If you are using it like this, you'll get RAM content on passed address, not the FLASH one. You have to use special functions for this. For example memcpy_P(ram_buff,flash_ptr); makes a copy from flash into the ram. Or you can read one byte by pgm_read_byte(flash_ptr + offset)
BTW: If you are using Data_6[0] and it's working, it's just because compiler sees it as a constant and constant can be replaced by its value compile time.
I Guess you just forgot to flush()
try to do Serial.flushI() after Serial.println(buff1[x],HEX);
you can also check flush documentation
I'm using Arduino Uno in my project : One is a Master and the other is a Slave. I send Data from the Master to the Slave using I2C. I need to send float, but because I2C can only send char, so I'm obligated to transform float into String, then send character by character, and assemble them in the Slave.
The problem I had is, I'm declaring the variable (in the Slave) that contain the Float receiving and assumbling from the Master like a global variable, and I need to use it in my code in the slave, but my problem is that it is always printed as 0, and it dosn't give the right value of it.
The code I'm using is :
#include <LCD16x2.h>
#include <Wire.h>
LCD16x2 lcd;
int buttons;
int sensorPin = A0; // select the input pin for the potentiometer
int sensorValue = 0; // variable to store the value coming from the sensor
float numOut=0; // The Global Variable
int comp=1 ;
String wordd = "";
void setup()
{
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
lcd.lcdGoToXY(1,1);
lcd.lcdClear();
lcd.lcdWrite("EG ");
lcd.lcdGoToXY(7,1);
lcd.lcdWrite(numOut,3);
}
void loop()
{
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
wordd = "";
int x = Wire.read();
for (int i=0; i<=x; i++)
{
char c = Wire.read();
wordd += c;
}
numOut = wordd.toFloat();
Serial.println(numOut,3); // print the integer
}
I need to know how to have the result of the global variable "numOut" to use it in my code.
Thank you in advance.!!
Did you actually check if the data received is correct ? I don't know about the Arduino's strings but if your toFloat() fails it might return 0.
Check through your serial port if your wordd variable is correct, and as already mentioned global variables should be declared as volatile.
EDIT:
volatile is necessary here to ensure your data is synchronized between your different function calls (otherwise your program might keep the value inside a register although the "real" value has been updated through an interrupt).
However as someone said volatile is NOT necessary to every global variable, but you won't be using semaphores/mutex... on an Arduino so stick witch volatile for the problem you posted.
EDIT:
https://www.arduino.cc/en/Reference/StringToFloat
"If no valid conversion could be performed because the string doesn't start with a digit, a zero is returned."
Don't know if there are any Arduino-wizards around here on StackOverflow, but I'm just gonna try and find one! I'm having issues understanding some code, and why I can't automate the process instead of pressing Enter.
I'm using an RFID reader to read some tags, and using the altSoftSerial library. However, in order to print the tagID to my serial, I need to press Enter. And for the love of God I can't figure out why that is. Isn't it possible to check the altSerial.read for a certain ID, and print it when it appears? Cause when I print the serial automatically I just get a lot of 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' noise...
#include <AltSoftSerial.h>
AltSoftSerial altSerial;
char txrxbuffer[255];
char get_readID[] = { 0xAA , 0x00, 0x03, 0x25, 0x26, 0x00, 0x00, 0xBB };
void setup()
{
Serial.begin(9600);
Serial.println("Hit Enter to read the RFID number");
altSerial.begin(9600);
}
void loop() // run over and over
{
int counter = 0;
if (Serial.available()){
Serial.read();
Serial.println("");
for (counter =0 ; counter < 8 ; counter++){
char tagID = get_readID[counter];
altSerial.write(tagID);
}
}
if (altSerial.available())
Serial.print(altSerial.read(),HEX);
}
seems like before reading a tag, you have to send a specific code to your rfod reader, code that you are sending in the first if; if at least one char is received on Serial (from pc), it read the char (but does not store it, it does so to clean the input buffer, so every char is a read, any char is good), and then send this code. The second if look for the answer and if present send it back to pc. So just send that code from setup() and then after every read, or look for an alternative commad that remain enabled