I want to transfer a number"500" stored in a variable "int3" from python to arduino via serial communication.
The arduino reads the data using Serial.read(), but prints only "5".
Thanks in advance.
I have int3, byte 2 and byte 3 to be sent from python, but want arduino to print the value of int3.
import serial
import time
ser=serial.Serial('/dev/ttyACM0',9600)
int3 = 500
int3 = b'%d' %int3
while (1):
ser.write(int3)
ser.write(b'2')
ser.write(b'3')
#print type(ser.write)
time.sleep(1)
print(int3)
String r;
void setup(){
Serial.begin(9600);
// while(!Serial)
// {
// ;
// }
}
void loop(){
if(Serial.available() > 0){
r =(Serial.read() - 0); //conveting the value of chars to integer
Serial.print(r[0]);
delay(100);
//while(Serial.available () !=0) r=Serial.read();
}
}
Replace the if with a while loop:
String fromRaspberry;
void loop(){
char c;
while (Serial.available() > 0) {
c = Serial.read(); //read char
fromRaspberry += c; //add the read char to string
}
int x = fromRaspberry.toInt(); //convert string to int
Serial.println(x);
// clear the string for new input:
fromRaspberry = "";
}
I would like to detect a certain byte pattern in an incoming byte stream at the UART. I am using Arduino. Currently, the code detects a single \r character. On this character is detected, the byte stream before this character gets stored into a buffer. This is easy. This is my code;
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0 ) {
// read the incoming byte:
incomingByte = Serial.read();
if (incomingByte != '\r') {
buffer_incoming_data[index_buffer]=incomingByte;
index_buffer++;
} else {
index_buffer = 0;
}
}
}
Here is my problem. Instead of a single character \r, I would like to detect a byte pattern that looks like this 0xAA 0xBB 0xCC. When this byte pattern is detected, the byte stream before byte pattern gets stored into a buffer.
Guess you invoke loop() method inside real loop operator. I can suggest next way:
int incomingByte = 0; // for incoming serial data
int pattern [] = {0xAA, 0xBB, 0xCC};
int patternIndex = 0;
int patternSize = sizeof(pattern)/sizeof(pattern[0]);
void loop() {
// send data only when you receive data:
if (Serial.available() > 0 ) {
// read the incoming byte:
incomingByte = Serial.read();
if(pattern[patternIndex] != incomingByte){
// if we found begin of pattern but didn't reach the end of it
if(patternIndex>0){
for(int i=0; i<=patternIndex-1; i++){
buffer_incoming_data[index_buffer]=pattern[i];
index_buffer++;
}
}
patternIndex = 0;
}
if(pattern[patternIndex] == incomingByte){
patternIndex++;
}else{
buffer_incoming_data[index_buffer]=incomingByte;
index_buffer++;
}
//if we reached the end of pattern
if(patternIndex==patternSize){
//do something with buffer
patternIndex = 0;
index_buffer = 0;
}
}
}
As you can see, I didn't check index_buffer for "index out of range" exception, but you should. Hope I helped you.
I am having a problem with the serial monitor on Arduino Uno.
Basically I want to write some commands on the Serial Monitor, read the string and according to the string do something.
The problem is the following: supposing I type the command 'read 4' in the Serial Monitor, sometimes the string is read correctly, sometimes it is read like: 'ead 4', missing the first character.
I even put a delay between two readings from the Serial Monitor. Does anyone have an explanation?
For completeness I post my code (basically it reads/writes from/to the EEPROM: for example 'read 5' will read the 5 block of EEPROM, 'write 4 5' will write the value 5 to the 4th block of memory).
#define MAX_STRING_LENGTH 14
#include <ctype.h>
#include <EEPROM.h>
//The function initializes the string to spaces
void initString(char* mystr, char strLength);
//The function returns true if it is a read operation, false otherwise
boolean isReadEEPROM(char *myStr, char strLength);
//The function returns true if it is a write operation, false otherwise
boolean isWriteEEPROM(char *myStr, char strLength);
//The function returns the EEPROM address from the string
unsigned int findAddress(char *myStr, char strLength);
char findValue(char *myStr, char strLength);
//Check the address range
boolean isAddressOk(unsigned int address);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
char pos = 0;
bool newDataFound = false;
char serialStr[MAX_STRING_LENGTH];
unsigned int address = 0;
char val = 0;
while(Serial.available()){
val = Serial.read();
}
val = 0;
initString(&serialStr[0], (char) MAX_STRING_LENGTH);
while(Serial.available() && pos < MAX_STRING_LENGTH){
serialStr[pos] = Serial.read();
pos ++;
newDataFound = true;
delay(200);
}
if (newDataFound){
Serial.print("New Command found: ");
Serial.println(serialStr);
address = 0;
address = findAddress(&serialStr[0], MAX_STRING_LENGTH);
if (isReadEEPROM(&serialStr[0], MAX_STRING_LENGTH) && isAddressOk(address)){
Serial.println("Reading from EEPROM");
Serial.print("Address is ");
Serial.println(address);
val = EEPROM.read(address);
Serial.print("Value is: ");
Serial.println( (uint8_t) val );
Serial.println(" ");
}
else if (isWriteEEPROM(&serialStr[0], MAX_STRING_LENGTH) && isAddressOk(address)){
Serial.println("Writing to EEPROM");
Serial.print("Address is ");
Serial.println(address);
Serial.println(" ");
val = findValue(&serialStr[0], MAX_STRING_LENGTH);
EEPROM.write(address, val);
}
else{
if (!isAddressOk(address)){
Serial.write(address);
Serial.println("Address out of range");
Serial.println("");
}
Serial.println("Not recognized operation\n");
}
delay(2000);
}
}
void initString(char* mystr, char strLength){
for(char ii=0; ii<strLength; ii++){
(*mystr) = ' ';
mystr++;
}
}
//The function returns true if it is a read operation, false otherwise
boolean isReadEEPROM(char *myStr, char strLength){
//The string should contain first the 'read' operation
char expected[] = "read";
int ii =0;
while (ii<4){
if ( *(myStr + ii) != expected[ii]){
return false;
Serial.println("Not a Read Operation\n");
}
ii++;
}
return true;
Serial.println("Read Operation");
}
//The function returns true if it is a write operation, false otherwise
boolean isWriteEEPROM(char *myStr, char strLength){
//The string should contain first the 'read' operation
char expected[] = "write";
int ii =0;
while (ii<5){
if ( *(myStr + ii) != expected[ii]){
return false;
}
ii++;
}
return true;
}
//The function returns the EEPROM address from the string
unsigned int findAddress(char *myStr, char strLength){
unsigned int address;
char tmpStr[strLength];
char strAddress[] = " ";
int ii = 0;
while(ii< strLength){
tmpStr[ii] = *(myStr+ii);
ii++;
}
Serial.print("The address found is: ");
Serial.println(strAddress);
ii= 0;
if (isReadEEPROM(myStr, strLength)){
while (ii<=4){
if (isdigit(*(myStr + 5 + ii))){
strAddress[ii] = *(myStr + 5 + ii);
}
else{
break;
}
ii++;
}
address = atoi(strAddress);
}
else if(isWriteEEPROM(myStr, strLength)){
while (ii<=4){
if (isdigit(*(myStr + 6 + ii))){
strAddress[ii] = *(myStr + 6 + ii);
}
else{
break;
}
ii++;
}
address = atoi(strAddress);
}
else{
address = 0;
//Serial.println("Address not available in function 'findAddress'");
}
return address;
}
//The function returns the value to be written to the EEPROM from the string
char findValue(char *myStr, char strLength){
char val;
char tmpStr[strLength];
char strVal[] = " ";
int ii, idx = 0;
while(ii< strLength){
tmpStr[ii] = *(myStr+ii);
ii++;
}
ii= 0;
// first found the first digits corresponding to the address
while (ii<=4){
if (isdigit(*(myStr + 6 + ii))){
;//strAddress[ii] = *(myStr + 6 + ii);
}
else{
ii++;
break;
}
ii++;
}
// now find the value
while (ii<=4+3){
Serial.println(*(myStr + 6 + ii));
if (isdigit(*(myStr + 6 + ii))){
strVal[idx] = *(myStr + 6 + ii);
}
else{
break;
}
ii++;
idx++;
}
Serial.print("original string: ");
Serial.println(tmpStr);
Serial.print("Value found: ");
Serial.println(strVal);
val = (char)atoi(strVal);
return val;
}
boolean isAddressOk(unsigned int address){
if (address < 1024 && address >= 0){
return true;
}
else{
return false;
}
}
This snippet:
char val=0;
while(Serial.available()){
val = Serial.read();
}
val = 0;
Is just consuming any characters that may be left in the input buffer. You could also do:
while (Serial.avaialble())
Serial.read();
The next while loop does not wait for the entire command. Sometimes, it gets the 'r', and then doesn't get the 'ead...' in time. They will be there the next time loop executes, so it looks like the 'r' is missing. It was just consumed in the previous loop.
Things sent over the USB (from the Serial Monitor window) can have odd delays in them.
To gather up a complete line, you should save characters until a '\n' is received:
for (;;) {
if (Serial.available()) {
char c = Serial.read();
if (c == '\n')
break;
if (pos < MAX_LINE_LENGTH) {
serialStr[pos] = c;
pos ++;
}
newDataFound = true;
}
}
The delay call is totally unnecessary, because the for loop waits until a '\n' character is received (be sure that in the Serial Monitor pull down menu either 'New Line' or 'both NL & CR' is selected). Then you know you've read all the characters in the line.
I am using keil c51 compiler. I transmit data from my pc to MCU using serial port it works best.
When I transmit data from my MCU to PC then also it works best.
But when I transmit data to MCU and then store it to buffer character pointer and again from that character pointer buffer I transmit return to PC then it does not work and give garbage values?
My code for both function as below.
#include <REG51.H>
#include "uart.c"
void delay_ms(unsigned int x) // delays x msec (at fosc=11.0592MHz)
{
unsigned char j=0;
while(x-- > 0)
{
for (j=0; j<125; j++){;}
}
}
sbit SW = P3^2;
sbit LED = P3^3;
bit x = 0;
void main ()
{
char *buf;
int len=0;
int len1 = 0;
uart_init();
while(1){
if(RI == 1){
UART_RxString(buf,&len);
buf -= (len-1) ;
x = 1;
}
if(x == 1 && SW == 0){
UART_TxString(buf,&len1);
x = 0;
}
}
}
And below are the functions.
1.
void UART_TxString(char *string_ptr, int *l)
{
int count = 0;
while(*string_ptr){
UART_TxChar(*string_ptr++);
count++;
}
*l = count;
}
void UART_RxString(char *string_ptr, int *l)
{
char ch;
int count = 0;
while(1)
{
ch=UART_RxChar(); //Reaceive a char
//UART_TxChar(ch); //Echo back the received char
count++;
if((ch=='\r') || (ch=='\n')) //read till enter key is pressed
{ //once enter key is pressed
*string_ptr=0; //null terminate the string
break; //and break the loop
}
*string_ptr=ch; //copy the char into string.
string_ptr++; //and increment the pointer
}
*l = count;
}
I'm using two Arduinos to sent plain text strings to each other using NewSoftSerial and an RF transceiver.
Each string is perhaps 20-30 characters in length. How do I convert Serial.read() into a string so I can do if x == "testing statements", etc.?
Unlimited string readed:
String content = "";
char character;
while(Serial.available()) {
character = Serial.read();
content.concat(character);
}
if (content != "") {
Serial.println(content);
}
From Help with Serial.Read() getting string:
char inData[20]; // Allocate some space for the string
char inChar = -1; // Where to store the character read
byte index = 0; // Index into array; where to store the character
void setup() {
Serial.begin(9600);
Serial.write("Power On");
}
char Comp(char* This) {
while (Serial.available() > 0) // Don't read unless there
// you know there is data
{
if(index < 19) // One less than the size of the array
{
inChar = Serial.read(); // Read a character
inData[index] = inChar; // Store it
index++; // Increment where to write next
inData[index] = '\0'; // Null terminate the string
}
}
if (strcmp(inData, This) == 0) {
for (int i=0; i<19; i++) {
inData[i] = 0;
}
index = 0;
return(0);
}
else {
return(1);
}
}
void loop()
{
if (Comp("m1 on") == 0) {
Serial.write("Motor 1 -> Online\n");
}
if (Comp("m1 off") == 0) {
Serial.write("Motor 1 -> Offline\n");
}
}
You can use Serial.readString() and Serial.readStringUntil() to parse strings from Serial on the Arduino.
You can also use Serial.parseInt() to read integer values from serial.
int x;
String str;
void loop()
{
if(Serial.available() > 0)
{
str = Serial.readStringUntil('\n');
x = Serial.parseInt();
}
}
The value to send over serial would be my string\n5 and the result would be str = "my string" and x = 5
I was asking the same question myself and after some research I found something like that.
It works like a charm for me. I use it to remote control my Arduino.
// Buffer to store incoming commands from serial port
String inData;
void setup() {
Serial.begin(9600);
Serial.println("Serial conection started, waiting for instructions...");
}
void loop() {
while (Serial.available() > 0)
{
char recieved = Serial.read();
inData += recieved;
// Process message when new line character is recieved
if (recieved == '\n')
{
Serial.print("Arduino Received: ");
Serial.print(inData);
// You can put some if and else here to process the message juste like that:
if(inData == "+++\n"){ // DON'T forget to add "\n" at the end of the string.
Serial.println("OK. Press h for help.");
}
inData = ""; // Clear recieved buffer
}
}
}
This would be way easier:
char data [21];
int number_of_bytes_received;
if(Serial.available() > 0)
{
number_of_bytes_received = Serial.readBytesUntil (13,data,20); // read bytes (max. 20) from buffer, untill <CR> (13). store bytes in data. count the bytes recieved.
data[number_of_bytes_received] = 0; // add a 0 terminator to the char array
}
bool result = strcmp (data, "whatever");
// strcmp returns 0; if inputs match.
// http://en.cppreference.com/w/c/string/byte/strcmp
if (result == 0)
{
Serial.println("data matches whatever");
}
else
{
Serial.println("data does not match whatever");
}
The best and most intuitive way is to use serialEvent() callback Arduino defines along with loop() and setup().
I've built a small library a while back that handles message reception, but never had time to opensource it.
This library receives \n terminated lines that represent a command and arbitrary payload, space-separated.
You can tweak it to use your own protocol easily.
First of all, a library, SerialReciever.h:
#ifndef __SERIAL_RECEIVER_H__
#define __SERIAL_RECEIVER_H__
class IncomingCommand {
private:
static boolean hasPayload;
public:
static String command;
static String payload;
static boolean isReady;
static void reset() {
isReady = false;
hasPayload = false;
command = "";
payload = "";
}
static boolean append(char c) {
if (c == '\n') {
isReady = true;
return true;
}
if (c == ' ' && !hasPayload) {
hasPayload = true;
return false;
}
if (hasPayload)
payload += c;
else
command += c;
return false;
}
};
boolean IncomingCommand::isReady = false;
boolean IncomingCommand::hasPayload = false;
String IncomingCommand::command = false;
String IncomingCommand::payload = false;
#endif // #ifndef __SERIAL_RECEIVER_H__
To use it, in your project do this:
#include <SerialReceiver.h>
void setup() {
Serial.begin(115200);
IncomingCommand::reset();
}
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
if (IncomingCommand::append(inChar))
return;
}
}
To use the received commands:
void loop() {
if (!IncomingCommand::isReady) {
delay(10);
return;
}
executeCommand(IncomingCommand::command, IncomingCommand::payload); // I use registry pattern to handle commands, but you are free to do whatever suits your project better.
IncomingCommand::reset();
Here is a more robust implementation that handles abnormal input and race conditions.
It detects unusually long input values and safely discards them. For example, if the source had an error and generated input without the expected terminator; or was malicious.
It ensures the string value is always null terminated (even when buffer size is completely filled).
It waits until the complete value is captured. For example, transmission delays could cause Serial.available() to return zero before the rest of the value finishes arriving.
Does not skip values when multiple values arrive quicker than they can be processed (subject to the limitations of the serial input buffer).
Can handle values that are a prefix of another value (e.g. "abc" and "abcd" can both be read in).
It deliberately uses character arrays instead of the String type, to be more efficient and to avoid memory problems. It also avoids using the readStringUntil() function, to not timeout before the input arrives.
The original question did not say how the variable length strings are defined, but I'll assume they are terminated by a single newline character - which turns this into a line reading problem.
int read_line(char* buffer, int bufsize)
{
for (int index = 0; index < bufsize; index++) {
// Wait until characters are available
while (Serial.available() == 0) {
}
char ch = Serial.read(); // read next character
Serial.print(ch); // echo it back: useful with the serial monitor (optional)
if (ch == '\n') {
buffer[index] = 0; // end of line reached: null terminate string
return index; // success: return length of string (zero if string is empty)
}
buffer[index] = ch; // Append character to buffer
}
// Reached end of buffer, but have not seen the end-of-line yet.
// Discard the rest of the line (safer than returning a partial line).
char ch;
do {
// Wait until characters are available
while (Serial.available() == 0) {
}
ch = Serial.read(); // read next character (and discard it)
Serial.print(ch); // echo it back
} while (ch != '\n');
buffer[0] = 0; // set buffer to empty string even though it should not be used
return -1; // error: return negative one to indicate the input was too long
}
Here is an example of it being used to read commands from the serial monitor:
const int LED_PIN = 13;
const int LINE_BUFFER_SIZE = 80; // max line length is one less than this
void setup() {
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
Serial.print("> ");
// Read command
char line[LINE_BUFFER_SIZE];
if (read_line(line, sizeof(line)) < 0) {
Serial.println("Error: line too long");
return; // skip command processing and try again on next iteration of loop
}
// Process command
if (strcmp(line, "off") == 0) {
digitalWrite(LED_PIN, LOW);
} else if (strcmp(line, "on") == 0) {
digitalWrite(LED_PIN, HIGH);
} else if (strcmp(line, "") == 0) {
// Empty line: no command
} else {
Serial.print("Error: unknown command: \"");
Serial.print(line);
Serial.println("\" (available commands: \"off\", \"on\")");
}
}
String content = "";
char character;
if(Serial.available() >0){
//reset this variable!
content = "";
//make string from chars
while(Serial.available()>0) {
character = Serial.read();
content.concat(character);
}
//send back
Serial.print("#");
Serial.print(content);
Serial.print("#");
Serial.flush();
}
If you want to read messages from the serial port and you need to deal with every single message separately I suggest separating messages into parts using a separator like this:
String getMessage()
{
String msg=""; //the message starts empty
byte ch; // the character that you use to construct the Message
byte d='#';// the separating symbol
if(Serial.available())// checks if there is a new message;
{
while(Serial.available() && Serial.peek()!=d)// while the message did not finish
{
ch=Serial.read();// get the character
msg+=(char)ch;//add the character to the message
delay(1);//wait for the next character
}
ch=Serial.read();// pop the '#' from the buffer
if(ch==d) // id finished
return msg;
else
return "NA";
}
else
return "NA"; // return "NA" if no message;
}
This way you will get a single message every time you use the function.
Credit for this goes to magma. Great answer, but here it is using c++ style strings instead of c style strings. Some users may find that easier.
String string = "";
char ch; // Where to store the character read
void setup() {
Serial.begin(9600);
Serial.write("Power On");
}
boolean Comp(String par) {
while (Serial.available() > 0) // Don't read unless
// there you know there is data
{
ch = Serial.read(); // Read a character
string += ch; // Add it
}
if (par == string) {
string = "";
return(true);
}
else {
//dont reset string
return(false);
}
}
void loop()
{
if (Comp("m1 on")) {
Serial.write("Motor 1 -> Online\n");
}
if (Comp("m1 off")) {
Serial.write("Motor 1 -> Offline\n");
}
}
If you're using concatenate method then don't forget to trim the string if you're working with if else method.
Use string append operator on the serial.read(). It works better than string.concat()
char r;
string mystring = "";
while(serial.available()){
r = serial.read();
mystring = mystring + r;
}
After you are done saving the stream in a string(mystring, in this case), use SubString functions to extract what you are looking for.
I could get away with this:
void setup() {
Serial.begin(9600);
}
void loop() {
String message = "";
while (Serial.available())
message.concat((char) Serial.read());
if (message != "")
Serial.println(message);
}
Many great answers, here is my 2 cents with exact functionality as requested in the question.
Plus it should be a bit easier to read and debug.
Code is tested up to 128 chars of input.
Tested on Arduino uno r3 (Arduino IDE 1.6.8)
Functionality:
Turns Arduino onboard led (pin 13) on or off using serial command input.
Commands:
LED.ON
LED.OFF
Note: Remember to change baud rate based on your board speed.
// Turns Arduino onboard led (pin 13) on or off using serial command input.
// Pin 13, a LED connected on most Arduino boards.
int const LED = 13;
// Serial Input Variables
int intLoopCounter = 0;
String strSerialInput = "";
// the setup routine runs once when you press reset:
void setup()
{
// initialize the digital pin as an output.
pinMode(LED, OUTPUT);
// initialize serial port
Serial.begin(250000); // CHANGE BAUD RATE based on the board speed.
// initialized
Serial.println("Initialized.");
}
// the loop routine runs over and over again forever:
void loop()
{
// Slow down a bit.
// Note: This may have to be increased for longer strings or increase the iteration in GetPossibleSerialData() function.
delay(1);
CheckAndExecuteSerialCommand();
}
void CheckAndExecuteSerialCommand()
{
//Get Data from Serial
String serialData = GetPossibleSerialData();
bool commandAccepted = false;
if (serialData.startsWith("LED.ON"))
{
commandAccepted = true;
digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level)
}
else if (serialData.startsWith("LED.OFF"))
{
commandAccepted = true;
digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW
}
else if (serialData != "")
{
Serial.println();
Serial.println("*** Command Failed ***");
Serial.println("\t" + serialData);
Serial.println();
Serial.println();
Serial.println("*** Invalid Command ***");
Serial.println();
Serial.println("Try:");
Serial.println("\tLED.ON");
Serial.println("\tLED.OFF");
Serial.println();
}
if (commandAccepted)
{
Serial.println();
Serial.println("*** Command Executed ***");
Serial.println("\t" + serialData);
Serial.println();
}
}
String GetPossibleSerialData()
{
String retVal;
int iteration = 10; // 10 times the time it takes to do the main loop
if (strSerialInput.length() > 0)
{
// Print the retreived string after looping 10(iteration) ex times
if (intLoopCounter > strSerialInput.length() + iteration)
{
retVal = strSerialInput;
strSerialInput = "";
intLoopCounter = 0;
}
intLoopCounter++;
}
return retVal;
}
void serialEvent()
{
while (Serial.available())
{
strSerialInput.concat((char) Serial.read());
}
}
This always works for me :)
String _SerialRead = "";
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available() > 0) //Only run when there is data available
{
_SerialRead += char(Serial.read()); //Here every received char will be
//added to _SerialRead
if (_SerialRead.indexOf("S") > 0) //Checks for the letter S
{
_SerialRead = ""; //Do something then clear the string
}
}
}