Why i can not receive string from USART using this code? - arduino

After using this code i am not getting anything on serial monitor while it should give me the string which i am sending .am i right that strings which i am sending from serial monitor are null terminated in arduino (and that's why i am waiting for null character in order to get the string) ? Please help
void setup()
{
UBRR0 = 103; // for configuring baud rate of 9600bps
UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00);
// Use 8-bit character sizes
UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
//// Turn on the transmission, reception, and Receive interrupt
sei();// enable global interrupt
}
ISR(USART_RX_vect)
{
while (1)
{
while (!(UCSR0A & (1 << RXC0)));
if (UDR0 != '\0')
{
buf[i] = UDR0;
i++;
}
else
{
break;
}
}
temp=String(buf);
uart_send_string(temp); //this function is working properly
}

No, you won't receive a null '\0' character usually.
Unless the sender explicitly sends one. But this is unusual for non-binary data transmission via Serial. The SerialMonitor definitely doesn't!
If you need to notice the end of a message, a newline ( LF , '\n' or 0x0A ) is very common. But any other character might do as well.
BTW: As you tag the question Arduino, why don't you use the Arduino library for Serial UART communication?

Related

Why does serial.available does not work in this code snippet?

I have a processing sketch which needs to set up 2 connections with USB devices. I cannot tell in advance which device is USB0 and which is USB1. (not that I am aware off atleast)
One of the devices awnsers with hello the other one does not answer at all. Therefor I have written code with a simple timeout. In the setup I check continously if there are bytes to read. But both a while and an if statement yield incorrect results
while( dccCentral.available() < 5 ) {
if( dccCentral.available() >= 5) break;
if(millis() > 5000 ) {
println("timeout occured");
println(dccCentral.available());
break;
}
}
These lines are in setup. The text "timeout occured" is always printed. Underneath it, the result of dccCentral.available() is printed. This number is 12 which is correct.
regardless, if dccCentral.available() prints 12 at that time. The first if-statement:
if( dccCentral.available() >= 5) break;
should already have break'ed out of the while loop before this time-out should occur. The while-loop itself should also quit itself when 5 or more bytes are received.
Why do both these lines
while( dccCentral.available() < 5 ) {
if( dccCentral.available() >= 5) break;
fail?
Personally I try to avoid while loops unless there isn't another way (e.g. inside a thread) and that is avoid both logic pitfalls and messing with the lifecycle of other objects that might need a bit of time to initialise.
If you send strings from Arduino and also use println() you could init the port to easily catch that using Serial's bufferUntil() in conjuction with serialEvent() to finally readString().
Once you start getting data in, you could:
use references to the serial ports you're after and a couple of extra ones until you know which port is which
use a boolean "toggle" to only handle the "hello" once
if the hello was received, you can use the serialEvent() Serial argument to assign dccCentral and by process of elimination assign the other port
Here's a commented sketch to illustrate the idea:
import processing.serial.*;
// be sure to set this to the baud rate your device use with Arduino as well
final int BAUD_RATE = 115200;
// reference to Serial port sending "Hello" (when that get's detected)
Serial dccCentral;
// reference to the other Serial port
Serial otherDevice;
// temporary references
Serial usb0;
Serial usb1;
// 'toggle' to keep track where the hello was received and handled or not (by default initialised as false)
boolean wasHelloReceived;
void setup(){
usb0 = initSerial("/dev/ttyUSB0", BAUD_RATE);
usb1 = initSerial("/dev/ttyUSB1", BAUD_RATE);
}
Serial initSerial(String portName, int baudRate){
Serial port = null;
try{
port = new Serial(this, portName, baudRate);
// if sending strings and using println() from Arduino
// you can buffer all chars until the new line ('\n') character is found
port.bufferUntil('\n');
}catch(Exception e){
println("error initialising port: " + portName);
println("double check name, cable connections and close other software using the same port");
e.printStackTrace();
}
return port;
}
void draw(){
background(0);
text("wasHelloReceived: " + wasHelloReceived + "\n"
+"dccCentral: " + dccCentral + "\n"
+"otherDevice: " + otherDevice , 10 ,15);
// do something with the devices once they're ready (e.g. send a message every 3 seconds)
if(millis() % 3000 == 0){
if(dccCentral != null){
dccCentral.write("ping\n");
}
if(otherDevice != null){
otherDevice.write("pong\n");
}
}
}
void serialEvent(Serial port){
try{
String serialString = port.readString();
// if the received string is not null, nor empty
if(serialString != null && !serialString.isEmpty()){
// for debugging purposes display the data received
println("received from serial: " + serialString);
// trim any white space
serialString = serialString.trim();
// check if "hello" was received
if(serialString.equals("hello")){
println("hello detected!");
// if the dccCEntral (hello sending) serial port wasn't assigned yet, assign it
// think of this as debouncing a button: setting the port once "hello" was received should happen only once
if(!wasHelloReceived){
// now what dccCentral is found, assign it to the named reference
dccCentral = port;
// by process elimiation, assign the other port
// (e.g. if dccCentral == usb0, then other is usb1 and vice versa)
otherDevice = (dccCentral == usb0 ? usb1 : usb0);
/*
the above is the same as
if(dccCentral == usb0){
otherDevice = usb1;
}else{
otherDevice = usb0;
}
*/
wasHelloReceived = true;
}
}
}
}catch(Exception e){
println("error processing serial data");
e.printStackTrace();
}
}
Note the above code hasn't been tested so it may include syntax errors, but hopefully the point gets across.
I can't help notice that USB0/USB1 are how serial devices sometimes show up on Linux.
If you're working with a Raspberry Pi I can recommend a slightly easier way if you're comfortable with Python. The PySerial has a few tricks up it's sleeve:
You can simply call: python -m serial.tools.list_ports -v which will list ports with extra information such as serial number of the serial converter chipset. This could be useful to tell which device is which, regardless of the manufacturer and USB port used
Other than the serial port name/location, it supports multiple ways (URLs) of accessing the port with a very clever: hwgrep:// will allow you to filter a device by it's unique serial number
Here's a basic list_ports -v output for two devices with the same chipset:
column 1
/dev/ttyUSB9
desc: TTL232R-3V3
hwid: USB VID:PID=0403:6001 SER=FT94O21P LOCATION=1-2.2
column 2
/dev/ttyUSB8
desc: TTL232R-3V3
hwid: USB VID:PID=0403:6001 SER=FT94MKCI LOCATION=1-2.1.4
To assign the devices using serial you would use something like:
"hwgrep://FT94O21P"
"hwgrep://FT94MKCI"
Update
It might help to step by step debug the system and try one port a time.
The idea is to get the bit of code reading the expected serial string tight.
Here's a basic example that should simply accumulate one char at a time into a string and display it:
import processing.serial.*;
Serial port;
String fromSerial = "";
void setup(){
size(300,300);
port = initSerial("/dev/ttyUSB0", 115200);
}
Serial initSerial(String portName, int baudRate){
Serial port = null;
try{
port = new Serial(this, portName, baudRate);
// if sending strings and using println() from Arduino
// you can buffer all chars until the new line ('\n') character is found
port.bufferUntil('\n');
}catch(Exception e){
println("error initialising port: " + portName);
println("double check name, cable connections and close other software using the same port");
e.printStackTrace();
}
return port;
}
void draw(){
if(port != null){
if(port.available() > 0){
char inChar = port.readChar();
fromSerial += inChar;
if(inChar == '\n'){
println("newline encountered");
println(fromSerial.split("\n"));
}
}
}
background(0);
text("from serial:" + fromSerial, 10,15);
}
If the data from dccCentral comes in a expected: great, the code can be simplfied and right conditions applied to filter the device in the future,
otherwise it should help pin point communication issues getting the "hello" in the first place (which would be 6 bytes ("hello"(5) + '\n') if sent with Serial.println() from Arduino)
Regarding Python, no problem at all. Should the idea help in the future you can check out this answer. (AFAIK Processing Serial uses JSSC behind the scenes)

How can I implement interrupt for serial USART communication for ATmega328P/Arduino Nano?

I have a small project for school that requires me to load data in the EEPROM of an ATmega328P through the USART serial communication. I'm going to figure out the EEPROM read/write myself.
I have problems sending data using interrupts. Basically, I want to have the Arduino Nano loop through code and when I send something through the USART serial communication using the serial monitor of the Arduino IDE, an interruption will occur and the data that was send will be saved in a variable.
My clock is 16 MHz, with a baud rate of 9600; and as I've said I'm using the Arduino IDE.
Here is what I've tried so far:
#define USART_BAUDRATE 9600
#define MYUBRR (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
void setup() {
UCSR0B = (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission and reception circuitry
UCSR0C = (1 << UCSZ00) | (1 << UCSZ01); // Use 8-bit character sizes
UBRR0H = (MYUBRR >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
UBRR0L = MYUBRR; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
UCSR0B |= (1 << RXCIE0); // Enable the USART Receive Complete interrupt (USART_RXC)
sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed
}
// Interrupt on receive
ISR (USART_RXC_vect)
{
char ReceivedByte;
ReceivedByte = UDR0; // Fetch the received byte value into the variable "ByteReceived"
UDR0 = ReceivedByte; // Echo back the received byte back to the computer
}
// Use the eeprom() function to read/write to EEPROM
void loop() {
}
I've copied and adapted the code from this site (first post).
(In the UCSR0C register, there is no URSEL bit that is mentioned in this post - the datasheet does not mention it and it gives me an error when I try to use it.)
But it seems that the interruption (as it is presented in the last part of the post) is not working for me. I've tested to see if I can read and write in the serial monitor using the following code:
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
UDR = ReceivedByte; // Echo back the received byte back to the computer
But this makes the controller wait for a data to be sent through the serial monitor, and then it prints it in the serial monitor. I do not want this behaviour.
Here is the datasheet that I've used to check my code: ATmega328P datasheet
Did I do something wrong? Did I forget something in my implementation of USART serial communication interrupt? What is actually wrong with my implementation? why is it not working?
I think you're going wrong here:
ISR (USART_RXC_vect)
{
char ReceivedByte;
ReceivedByte = UDR0; // Fetch the received byte value into the variable "ByteReceived"
UDR0 = ReceivedByte; // Echo back the received byte back to the computer
}
In the above code you're basically saying UDR0 = UDR0. You need to give some time between these two lines of code in order to obtain the desired effect. If you take a look at the AVR freaks link you posted, they have this line in between:
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it

Can UDR be written inside USART_RXC interrupt handler without checking the UDRE flag in AVR ATMega32?

I have been trying to understand this code which is supposed to echo each byte received on the AVR's USART interface using interrupt.
#include
#include
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
int main (void)
{
UCSRB = (1 << RXEN) | (1 << TXEN); // Turn on the transmission and reception circuitry
UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
UCSRB |= (1 << RCXIE); // Enable the USART Recieve Complete interrupt (USART_RXC)
sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed
for (;;) // Loop forever
{
// Do nothing - echoing is handled by the ISR instead of in the main loop
}
}
ISR(USART_RXC_vect)
{
char ReceivedByte;
ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"
UDR = ReceivedByte; // Echo back the received byte back to the computer
}
I'm having troubles understanding this part
ISR(USART_RXC_vect)
{
char ReceivedByte;
ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"
UDR = ReceivedByte; // Echo back the received byte back to the computer
}
Why isnt the UDRE flag checked here to see if indeed new data can be written, without overwriting previous data? Since we do the same thing in the corresponding polling approach:
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
UDR = ReceivedByte; // Echo back the received byte back to the computer
Shouldn't there be a checking for the UDRE flag before the UDR = ReceivedByte; line inside the ISR too?
Any insights would be much appreciated.
Short answer is - yes: you can write UDR in any time you want, without any checks ahead.
But, if output buffer is full (the UDRE flag in UCSRA is not set) then written data will be ignored by the transmitter, or, in other words, it will be lost.
The USART module have a double output buffer. That means it is possible to write there two bytes ahead: one is being transmitted right now and one in the buffer will be transmitted later. UDRE flags show when the buffer byte is empty, while TXC flag shows when transmitting byte is pulled out.
So, if you have a way to be sure the transmitter buffer will not be overrun, then it is possible not to check that flag at all. Since receiving of the byte requires exactly the same time as transmitting, you can be sure that RXC interrupts will not be happened more often than bytes will be transmitted, so, it if UDR is not written elsewhere, it is possible to assume that output buffer can always accept at least one-byte, when RXC interrupt happens.
Still, if UDR is written somewhere else, it is possible that output buffer will not be empty, when RXC interrupt is happened, so transmitted echo byte will be lost.
At the other hand, the good programming practice is to leave interrupt handlers as soon as possible. Putting wait loops in the interrupt handler routine is a bad idea. In that case, if you can not be sure the output buffer will be empty on the RXC event, better to either have some kind of output buffer in RAM, which will be processed in UDRE interrupt, or to perform echo outside the RXC interrupt.

Atmega 2560 USART not giving correct value on terminal

I am working on the serial communication of my MultiWii Pro board, which is based on a atmega2560. I am using avr-gcc to compile and avrdude to program.
Here is my problem. I am trying to get atmega2560 to send something (hex value) to the terminal. However, regardless of the value assigned to UDR2 and regardless the value I assigned to UBRR2L and UBRR2H, the terminal output is always 0xff if I set the terminal baud-rate at 9600, and 0xff if I set the terminal baud-rate at 115200.
Here is my code
#define F_CPU 8000000UL
#define BAUDRATE 19200 //The baudrate to use
#define BAUD_PRESCALLER ((F_CPU / (BAUDRATE * 16UL))-1)
static void InitializeUART()
{
UBRR2L = (uint8_t)(BAUD_PRESCALLER);
UBRR2H = (uint8_t)(BAUD_PRESCALLER>>8);
UCSR2B |= (1<<RXEN2) | (1<<TXEN2); //RX TX Enable
UCSR2C |= (1<<USBS2)|(1<<UCSZ21)|(1<<UCSZ20);
}
And my sending function
void USART2Write(char data)
{
while( !(UCSR2A & (1<<UDRE2)));
UCSR2B &= ~(1<<TXB82); //in the case if there are more than 8 bits of data
if(data & 0x100)
{
UCSR2B |= (1 << TXB82);
}
UDR2 = data;
}
In my case, the baudrate of my code is 19200. The terminal baudrate is also 19200. No matter what I assigned to UDR2, the output will always be 0x15.
Here is my fuse setting
Low High Extended
0xFF 0xD8 0xFD
UCSR2C |= (1<<USBS2)|(1<<UCSZ21)|(1<<UCSZ20);
USBS2 sets 2 stop bits. Is this intentional?
void USART2Write(char data){
while( !(UCSR2A & (1<<UDRE2)));
UCSR2B &= ~(1<<TXB82); //in the case if there are more than 8 bits of data
if(data & 0x100) {
UCSR2B |= (1 << TXB82);
}
UDR2 = data;
}
If you really want to use 9 data bits, UCSZ22, UCSZ21 and UCSZ20 have to be set. YOu only set UCSZ21 and UCSZ20
UCSR2C |= (1<<USBS2) | (1<<UCSZ21) | (1<<UCSZ20);
so I guess that USBS2 is indeed not what you want here. Maybe you were confused because the flag UCSZ22 is in the UCSR2B register.
So assuming you want 9 data bits and one stop bit use something like this:
static void InitializeUART() {
UBRR2L = (uint8_t)(BAUD_PRESCALLER);
UBRR2H = (uint8_t)(BAUD_PRESCALLER>>8);
UCSR2B |= (1 << RXEN2) | (1 << TXEN2) | (1 << UCSZ22);
UCSR2C |= (1 << UCSZ21) | (1 << UCSZ20);
}
Another thing: Your variable data is of type char and char is normally 8 bit wide. So the condition if(data & 0x100) is never satisfied.

How to capture a variable stream of characters and process them on a Arduino using serial?

I'm trying to read variable streams of characters and process them on the Arduino once a certain string of bytes is read on the Arduino. I have a sample sketch like the following, but I can't figure out how to compare the "readString" to process something on the Arduino. I would like the Arduino to process "commands" such as {blink}, {open_valve}, {close_valve}, etc.
// Serial - read bytes into string variable for string
String readString;
// Arduino serial read - example
int incomingByte;
// flow_A LED
int led = 4;
void setup() {
Serial.begin(2400); // Open serial port and set Baud rate to 2400.
Serial.write("Power on test");
}
void loop() {
while (Serial.available()) {
delay(10);
if (Serial.available() > 0) {
char c = Serial.read(); // Gets one byte from serial buffer
readString += c; // Makes the string readString
}
}
if (readString.length() > 0) {
Serial.println( readString); // See what was received
}
if (readString == '{blink_Flow_A}') {
digitalWrite(led, HIGH); // Turn the LED on (HIGH is the voltage level).
delay(1000); // Wait for one second.
digitalWrite(led, LOW); // Turn the LED off by making the voltage LOW.
delay(1000); // Wait for a second.
}
Some definitions first:
SOP = Start Of Packet (in your case, an opening brace)
EOP = End Of Packet (in your case, a closing brace)
PAYLOAD = the characters between SOP and EOP
PACKET = SOP + PAYLOAD + EOP
Example:
PACKET= {Abc}
SOP = {
EOP = }
PAYLOAD = Abc
Your code should process one character at a time, and should be structured as a state machine.
When the code starts, the parser state is "I'm waiting for the SOP character". While in this state, you throw away every character you receive unless it's equal to SOP.
When you find you received a SOP char, you change the parser state to "I'm receiving the payload". You store every character from now on into a buffer, until you either see an EOP character or exhaust the buffer (more on this in a moment). If you see the EOP char, you "close" the buffer by appending a NULL character (i.e. 0x00) so that it becomes a standard NULL-terminated C-string, and you can work on it with the standard functions (strcmp, strstr, strchr, etc.).
At this point you pass the buffer to a "process()" function, which executes the operation specified by the payload (1)
You have to specify the maximum length of a packet, and size the receive buffer accordingly. You also have to keep track of the current payload length during the "payload receive" state, so you don't accidentally try to store more payload bytes into the temporary buffer than it can hold (otherwise you get memory corruption).
If you fill the receive buffer without seeing an EOP character, then that packet is either malformed (too long) or a transmission error changed the EOP character into something else. In either case you should discard the buffer contents and go back to "Waiting for SOP" state.
Depending on the protocol design, you could send an error code to the PC so the person typing at the terminal or the software on that side knows the last command it sent was invalid or not received correctly.
Finally, the blink code in you snipped should be replaced by non-blocking "blink-without-delay"-style code (look at the example that come with the Arduino IDE).
(1) Example of a "process" function:
void process(char* cmd) {
if (strcmp(cmd, "open_valve") == 0) {
open_valve();
}
else if (strcmp(cmd, "close_valve") == 0) {
close_valve();
}
else {
print_error("Unrecognized command.");
}
}
It seems you are comparing the string in this statement:
if( readString == '{blink_Flow_A}' )
So I don't get your question re :
but I can't figure out how to compare the "readString" to process something
Are you really asking:
How do I extract the commands from an incoming stream of characters?
If that is the case then treat each command as a "packet". The packet is enclosed in brackets: {}. Knowing that the {} brackets are start and end of a packet, it is easy to write a routine to get at the command in the packet.
Once the command is extracted just go through a if-then-else statement to do what each command is supposed to do.
If I totally misunderstood your question I apologize :)
EDIT:
see http://arduino.cc/en/Tutorial/StringComparisonOperators
if( readString == "{blink_Flow_A}" ) should be correct syntax.
Since you have a statement
Serial.println( readString);
you should see the string received.

Resources