Arduino incoming byte - arduino

I'm building a system using two ultrasonic sensors and sending data through Xbee. I'm using two nodes in AT end point, one coordinator in AT mode as well.
For testing I've used the basic Arduino example:
if(Serial.available > 0) {
incomingByte = Serial.read();
if(incomingByte == 'H') {
//DO SOMETHING
}
}
It works fine for byte coming from 1 node.
How can I implement to check if incomingByte is receiving data from node1 and node2 at the same time?

you can't. Serial is born to be used by only two pair, infact it sdoes not have data collision managment (that mean if the sensor write toghedere, you will get ureadable data).
you can see the xbee as a serial, but that has collision detection and resolve under the hood. So you can't have parallel message.
You can add to the packet the time of the reading, and usa that
Also you can't use two ultrasonic togheder without taking big precautions as they will affect each others.

Related

Send data to Arduino at any time

I am working on an embedded system whose microcontroller is an Arduino chip (Arduino Nano ATmega328P).
I can connect to it with a FTDI cable to read its outputs using a serial terminal. Now I want to communicate with it the other way around, that is, sending it messages or codes in order to change its global parameters.
I know it is possible to do so if I write some code where the Arduino is doing nothing but listening to the serial port. But I would like to be able to send it message at any time, even when it is doing something else. Sending it a message could trigger an interrupt, then the Arduino would execute a parallel script where it listens to the serial port for some time...
Can I do that, or is it not possible with an Arduino ?
Thanks :)
As far as I know (could be wrong), you can not "multi-thread" an arduino (don't know of any microcontrollers that support this). Inherently microcontrollers should be coded in a different style from computers. You can not assume infinite resources and infinite threads. Instead it is all about your main loop speed and how to distribute your resources. The arduino example (blink without delay) is an example of how this is done with timers. Basically, you put all of your processes inside their own timers so that they execute once per timer interval and are skipped at all other times. Assuming none of your processes are in the main loop, this will allow context switching after each and every process, as the program will cycle back through the main loop looking for the next task timer to come up. If you put all of your cyclical processes on timers like this, then put your serial availability check in another (pretty high frequency) timer, and grab serial any time you see it, it will I believe give you the results that you are after. Keep in mind though that serial read and write is a relatively slow process and so after reading or writing you may need to be careful about other processes that depend on a tight frequency call (like reading a mic to determine sound frequency for instance would need to be reset every time you read serial).
--edit
I was literally working on this today anyways, so here you go:
*note that i had no need to read incoming serial, so left that bit to you to figure out. (but showed where it would be done)
boolean resetMicRecording = true;
unsigned long microphoneTimer = 0;
unsigned long microphonePeriod = 100; //us
unsigned long serialTimer = 0;
unsigned long serialPeriod = 500; //ms
void setup() {
Serial.begin(9600);
}
void loop() {
if (micros() - microphoneTimer >= microphonePeriod)
{
microphoneTimer = micros();
//do microphone task
if(resetMicRecording)//first time flag
{
//set inital recording stuff
resetMicRecording = false;
}
else//consistent frequency sampling
{
//precision analog reading, logging, and processing if nec
}
}
if (millis() - serialTimer >= serialPeriod)
{
serialTimer = millis();
if(Serial.available()>0)
{
//read your incoming serial here
//reset sensitive device timers to startup
resetMicRecording = true;
}
}
}

How to handle ISR callback?

I am currently working on a larger Arduino Mega 2560 project; servo controlling and sensor readings involved. I am using ultrasonic proximity sensors (HC-SR04) with the NewPing 1.8 library that uses interrupts for detecting the echo of the sensors. Furthermore, I read temperature and light intensity measurements also. Distance data received from the HC-SR04 ultrasonic sensors are forwarded over USB to the host computer by using the cmdMessenger3 library. Servos are controlled by messages from the host computer using the standard Servo library.
The mess begins as soon as the NewPing library calls the ISR when the ultrasonic echo is detected. This is the function called by the NewPing library when distance data is available:
void sendSonarData(uint8_t sensorId, uint16_t distance) {
//noInterrupts();
cmdMsg3.sendCmdStart(kReadSonar);
cmdMsg3.sendCmdArg(sensorId);
cmdMsg3.sendCmdArg(distance);
cmdMsg3.sendCmdEnd();
//interrupts();
}
Here's another callback that sends temperature data to the host computer by the cmdMessenger3 library:
void sendTemperatureData(uint8_t sensorId, uint16_t temperature) {
//noInterrupts();
cmdMsg3.sendCmdStart(kReadTemperature);
cmdMsg3.sendCmdArg(sensorId);
cmdMsg3.sendCmdArg(temperature);
cmdMsg3.sendCmdEnd();
//interrupts();
}
Problem: While the Arduino e.g. tries to send the temperature data, the ISR from the ultrasonic sensor might jump-in and writes it's own data to the serial stream; ending up in a mess regarding the serial data sent to the host computer, because the sending process is not atomic, consisting of multiple commands to send one message (sendCmdStart->sendCmdArg->sendCmdEnd).
Here's an example:
Temperature is read an sendTemperatureData(...) is called
cmdMsg3.sendCmdStart(kReadTemperature); is called
cmdMsg3.sendCmdArg(sensorId); is called
ISR from sonar sensor jumps-in
sendTemperatureData(); is called
cmdMsg3.sendCmdStart(kReadSonar); is called
cmdMsg3.sendCmdArg(sensorId);
cmdMsg3.sendCmdArg(distance);
cmdMsg3.sendCmdEnd();
remaining statements from sendTemperatureData(...) are called
cmdMsg3.sendCmdArg(temperature);
cmdMsg3.sendCmdEnd();
resulting in a big mess on the serial communication ...
I then tried to prevent ISR calls during the send process by using noInterrupts()/interrupts(); making the send process kind of 'atomic'. But this leads to lots of other problems, millis()/micros() functions are not precise anymore, Serial communication breaks down, etc.; all relying on the timers that are disabled by noInterrupts(). Moreover, the servos behave also quite strange, since timing for the PWM signal generation seems to be messed up also.
Any ideas how to solve this 'concurrency' issue without breaking the interrupt-based paradigm in my program?
You are trying to do WAY to much work in your ISRs; generally speaking, they shouldn't do anything that requires a delay (and any serial message over 1 byte falls in that category). A more reasonable implementation would have the ISR simply store the sensor reading in global variables, and set a flag that the main program checks to see if it should send the serial message. You might need something fancier (like a message queue) if a second reading from the same sensor might arrive before the previous one had a chance to be sent.

Arduino Uno - Light Switch

The function of the program I am writing is to stream incoming analog data from a sensor to a program on my computer across the USB port. For a little fun, I've decided to add a button to the program that will turn on/off a lamp. The lamp will be connected to a relay, which is connected to the arduino. I know how to go about programming it, but I want to know if this will interrupt the sensor data transfer?
I will get the current state of the light (HIGH(1) or LOW(0)) from the arduino when the button is pressed, then write to the arduino (HIGH(1) or LOW(0)) depending on the current state. I have a 5 second delay between each loop of the arduino program, for reasons related to the sensor output; however, I think I'm going to have to change this so that when the button is pressed, it is not missed by the arduino loop, or is that not possible?
I thought I read somewhere that you can't transmit/receive streaming data on the same serial line...in which case, I will need the Mega.
You have to remember and think of the Arduino as a single threaded device. While it is doing anything it is not able to do anything else. Period! In regard to the serial port however, the buffer will still accept incoming data on RX, however if an overflow situation occurs whilst blocked, management is impossible.
See the following taken directly from the Arduino reference
Certain things do go on while the delay() function is controlling the Atmega chip however, because the delay function does not disable interrupts. Serial communication that appears at the RX pin is recorded, PWM (analogWrite) values and pin states are maintained, and interrupts will work as they should. Reference
Now in saying that when you are setting the delay to 5 seconds between loops ( delay(5000) ) you are essentially blocking it from doing anything else almost full stop.
The Arduino framework exposes a a counter ( millis() ) that basically runs from the moment of boot for roughly 50 days in increments of one (1) millisecond. See Arduino - millis()
In your application you would define (remember) what loop you were due to run & when the said loop had finished so to not allow the other loop to run until the millis() counter was a defined amount more than your count. (Remember to define the count as a long)
Then what you do is move your loops out into separate functions that will only execute if the if statement return true...
for example...
long interval = 5000; // Define interval outside of the main loop
long previousCount = 0; // Used to store milli count when finished
int loopPosition = 1;
void loop()
{
if ((long)millis() - previousCount >= 5000 )
// This if statement will only return true every 5 seconds (5000ms)
{
if (loopPosition == 1)
{
function_One();
previousCount = millis(); // Redefine previousCount to now
loopPosition++; // Increment loop position
}
else if (loopPosition == 2)
{
function_Two();
previousCount = millis();
loopPosition--; // Decrement loop position
}
}
// Do Anything Here You Want
// - While ever the if statement above returns false
// the loop will move to this without hesitation so
// you can do things like monitor a pin low / high scenario.
}
void function_One()
{
// Do Your First Loop
}
void function_Two()
{
// Do Your Second Loop
}
The above will stop any delay you are using from blocking awesomeness, and to more of a point, almost make delay obsolete if implemented correctly under the right scenarios.
In regard to your serial data comment, like i said at the top of this article, the Arduino can only do one thing at a time. Transmitting and receiving at exactly the same time is impossible even with the Mega. In saying that a board like the 'Uno' for example is only capable of one serial interface, where as the 'Mega' is capable of four.
Best of luck....
NB- For a beginner reading this, the following tutorial / example covers what i have above in fairly simple terms and is a great building block for further awesomeness! Arduino - Blink Without Delay

Arduino interrupt handling

Background
I have need for a data logging application running on a "Arduino compatible" chipKit UNO32 board, with a connected sensor. Data should be logged to an SD-card found on a "Arduino Wireless SD shield".
The sensor is connected via I2C.
My problem is that when I use the Arduino SD library writing is slow: 25 ms per print() operation, which gives me a maximum of 40 Hz which is laughable compared to the 100-800Hz data rate of my sensor.
My faulty solution
Luckily the sensor comes equipped with both an on-chip FIFO that can store 32 sensor values. This means I can go to at least 200Hz without any troubles since the time to fill the FIFO is way larger than the time to write to the card.
But I'd still really like to get to at least 400Hz, so I thought I'd have the following setup:
Tell sensor to put data in the FIFO
When the FIFO is almost full, the sensor triggers an interrupt (sensor does this, and it works, I can catch the interrupt)
When the Arduino receives the interrupt, it polls the sensor for data (via I2C) and stores the data in a buffer in SRAM.
When the SRAM buffer is getting full, write its contents to the SD-card.
Unfortunately, this does not seem to work since the Arduino Wire library that handles I2C use interrupts, and can not be called from within an interrupt handler. I have tried it, and it freezes the microcontroller.
My question
There seems to be other I2C libraries for Arduino that do not rely on interrupts. Should I try that route?
Or is my way of thinking (grabbing a load of data in an ISR) bad from start? Is there another approach I should take?
Just use the interrupt to set a flag and finish the ISR. from the main loop do the calling I2C instead of directly calling from ISR.
boolean fifoFull = false;
void fifoISR() {
fifoFull = true;
}
void loop() {
if(fifoFull) {
// Do I2C
fifoFull = false;
}
}

Two port receive using software serial on Arduino

i am having trouble getting data from two sensors using two software serial ports with an arduino board. I noticed a similar question might have been asked before but the answers suggest it can't be done and I know fully well it can based on the example here (http://arduino.cc/en/Tutorial/TwoPortReceive)!
I am using an arduino ethernet. The devices I am trying to get data from include a GPS and an IMU both from sparkfun.
I can get data from either devices using just on software serial port but as soon as I add the second software serial port, neither ports will work. I can't use the hardware serial port because that is being used byt another device.
My code is exactly similar to the example:
#include <SoftwareSerial.h>
SoftwareSerial portOne(7,8);
SoftwareSerial portTwo(5,6);
void setup()
{
Serial.begin(9600);
portOne.begin(9600);
portTwo.begin(9600);
}
void loop()
{
portOne.listen();
while (portOne.available() > 0) {
char inByte = portOne.read();
Serial.write(inByte);
}
delay(500);
portTwo.listen();
while (portTwo.available() > 0) {
char inByte = portTwo.read();
Serial.write(inByte);
}
Serial.println();
}
Anyone with any ideas?
This code will not work, or will work poorly if it works at all. SoftwareSerial only has one internal buffer. Yes, you can have multiple SoftwareSerial objects in existence, but only one of them controls the internal buffer. When any RX pin gets asserted, that generates an interrupt, but only the listen()ing RX pin gets checked for a start bit.
What's really needed is the ability to check on multiple pins when an interrupt comes along from the start bit. Then you'd have to set up pointers to the appropriate data structures. It would be complicated, but possible.
Or maybe just give up on interrupt-driven reception, and spin on checking both/all of the RX pins, and start the receive based on the pin you see. Be forwarned that this code has much hair, and you WILL need an oscilloscope to make it work.
I'm having a similar problem, which is why I found your sensor. After talking it over with my co-workers, we've decided to read our sensors in rotating order. Our sensors report the current state of the sensor, and not specific events, so it's okay if we lose some reports. So we'll read from port 1, then read from port 2, then port 1, etc. Our sensors spit out lines of text, so we know when to switch to the next sensor.
The referenced example only actively listens to one port at a time. The recommended solution would be to upgrade to an Arduino Mega (https://www.sparkfun.com/products/11061) which has 4 hardware serial ports.
In order to simultaneously support two software serial ports is going to require a lot of the CPU resources. It also be a difficult design and excessive programming time far outweighing the cost of $58 + shipping.
Looking at you code again it occurs to me that you are immediately checking for characters after your portOne.listen command. At 9600 baud it will take approximately 1ms for the first character to arrive, your while test will have been completed and the portTwo.listen command executed long before the first character arrives.
For testing purposes try adding a 1-2 ms delay after the portOne.listen command and see if you get a character.
As an example (untested and note, if port one is sending characters with no intercharacter gaps, the first while will never fail, preventing reading portTwo characters):
void loop()
{
portOne.listen();
delay(2);
while (portOne.available() > 0) {
char inByte = portOne.read();
Serial.write(inByte);
delay(1);
}
portTwo.listen();
delay(2);
while (portTwo.available() > 0) {
char inByte = portTwo.read();
Serial.write(inByte);
delay(1);
}
Serial.println();
}
Don't use while ......
Use:
{ portOne.listen();
if (PortOne.available() ) {
ricevo = myPort1.read(); }
// delay(2); // ridiculos waiting time
// delay(1); // extra ridiculos waiting time
Than 500 ms is a too big time for switching, no time.....

Resources