Stuck in a for loop in Arduino IDE - arduino

I'm using Arduino to look for I2C addresses, and half way through this new glitch appeared, and I don't know if it's the IDE or if I'm going insane.
I know most of this probably isn't important, but I don't know what is going on so here is my entire loop.
void loop(){
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 0; address <= 255; address++ )
{
Wire.beginTransmission(address);
error = Wire.endTransmission();
Serial.print(address);
Serial.print("|");
Serial.println(error);
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print("Unknow error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
delay(200);
//Serial.println(address);
}
delay(150);
Serial.println("Exiting");
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(30000);
exit(0);
}
As you can see in the picture I included the for loop returns to address=0 without printing anything after it, or before it in the loop(). Why is this happening?

I'm sure it has to do with you declaring address as a byte which is can be the integer 255 at max. What happens is if you add 1 to a byte value of 255, it loops around again to 0.
What happens when address = 255 and when the for loop goes back up to check the conditioning, 255 passes and address++ adds 1 to address so now address = 0.
https://www.arduino.cc/en/reference/byte

Alternatively, you could use a while loop instead and increment the address counter at the very end of the loop, followed by a test to see if it has wrapped around to zero. On the first run through of the loop, the address counter will be 1, so the loop will continue until the counter has reached 255 when the increment will wrap it around to zero and execution reaches the break statement.
byte address = 0;
while( true ) // Creating an unconditional loop
{
// Run your test here
address++;
if( !address ) // If address has wrapped around to 0, exit the loop
{
break;
}
}
...or a do/while loop, which does the same thing but may be slightly larger in some cases.
byte address = 0;
do
{
// Run your test here
address++;
} while( address ); // The loop will continue until address becomes zero again
Depending on your microcontroller, this may take a few bytes more program space though it looks like the while-loop ends up the same size as the for-loop on an ATMega328. (YMMV, of course)
On 8-bit microcontrollers however, code to manipulate ints will be slower and take up more space, so depending on your code you may still be better off by being able to stick with using a byte for your address.

Related

Why does the IR reciver gives diffrent value everytime I try to break a for loop - when new value is recived, Arduino ide?

I am new to Arduino programming and was trying to make an IR-controlled WS2812 led strip light, everything works fine apart from when I try to stop the for-loop when my IR receiver gets a new decoded value. It does get the job done but the received values are different every time. when I tested the same controller with a simple IR receiver program everything worked fine.
switch(value){
case 16720095:
delay (200);
irrecv.resume();
for (int i = 0; i <= 182; i++) {
leds[i] = CRGB (0,0,0);
FastLED.show();
if (irrecv.decode(&results))
{
value = results.value;
Serial.println(value);
break;
}
delay(40);
}
}
}
and the serial outputs:
first time:
16720095
-1572362453
second time:
16720095
-1406992986
third time:
16720095
811035822
It looks like you need to call "irrecv.resume()" within the if (irrecv.decode(&results)) block in order to tell the driver to keep looking for signals. The second values you are getting are garbage because you are asking it to provide data it hasn't received/ prepared.

How to read string using Serial.read outside of loop()?

I want to read a String in Arduino from the keyboard outside of the loop() method.
I have the following method:
void readFromKeyboard(byte arrayAddress[])
{
int count = 0, i = 0;
while ((count = Serial.available()) == 0);
while (i<count)
{
arrayAddress[i++] = Serial.read();
}
}
In the loop() method I am calling it like:
readFromKeyboard(userInput);
where userInput is a byte[];
The problem is that when I input more than one characters it read the 1st character initially and it call the readFromKeyboard again an then reads the rest.
Example; if I input "asdf":
--the 1st time it will do ==> userInput = "a"
--the 2nd time it will do ==> userInput = "sdf"
I have tryed many things but the same happens again and again...
Any suggestions??
So that's what worked:
In the loop():
while(Serial.available() == 0);
delay(100);
readInputFlag = readFromKeyboard(userInput);`
And in the readFromKeyboard method:
void readFromKeyboard(byte arrayAddress[])
{
int i = 0;
while (Serial.available() > 0)
{
arrayAddress[i++] = Serial.read();
}
}
This delay, in the loop method, somehow makes the Serial get the whole string instead of just the first letter.
I know you got it working, but I wanted to show you something that I use to deal with this issue. This is a two-tiered delay system for catching bytes that come in a bit late for whatever reason. It's designed to minimize the delay needed to accomplish that task.
int received_length = 0;
byte serial_incoming_buffer[200];
while(Serial.available()) {
serial_incoming_buffer[received_length++] = Serial.read();
if(!Serial.available()) {
delay(3);
if(!Serial.available()) {
delay(20);
}
}
}
Sometimes the Arduino falls behind in picking up serial from the sender and sometimes it grabs serial too fast. Sometimes the sender lags a little bit. This code will wait 3 ms for more bytes, and if they come in it goes back to receiving as many as are available having only had that very brief delay. This repeats as necessary, then when 3 ms goes by without anything being available, it waits a bit longer (20 ms here) for more bytes. If nothing comes in after the long delay, then the transmission is most likely done and you can safely move on.
I recommend tweaking the delays based on your baud rate.

Timing Issue Using PySerial with Arduino Uno

Here's the big picture:
I'm trying to control a stepper motor by recording a set of positions and then playing them back. To control the steppers I am using AccelStepper.
Since the movement data is large I need to store it on my Mac and send it over to the Arduino using the Serial connection.
Also, I can't afford delays because of the way AccelStepper works.
Here's the issue:
The code below works when I insert a delay of about 60ms or more. However, this screws up AccelStepper.
My understanding of this is that the first while loop "listens" to the serial line. If there is nothing to read, I send an 'A' to the Mac to request some data. This loop breaks when there is data available to read.
The second loop reads the serial line until encountering a newline character. This code works with the delay and does not without a delay.
Does that make sense?
Thank-you.
================================
if (stepper.distanceToGo() == 0)
{
while (Serial.available() <= 0) { // Ask Mac for more data.
Serial.print("A");
delay(60); // Argh line!
stepper.runSpeedToPosition();
}
while(Serial.available() > 0) { // There's info on the serial line
character = Serial.read();
content.concat(character);
if (character == '\n') break; // Keep reading until newline
stepper.runSpeedToPosition();
}
Without delay, the while loop will take "all" your system (CPU) resources, actually delaying the interrupt from the serial line. The 60 is very specific value though.
So an option is to rewrite the loop and test if this helps:
if (stepper.distanceToGo() == 0) {
while (true) {
if(Serial.available() <= 0) { // Ask Mac for more data.
Serial.print("A");
stepper.runSpeedToPosition();
} else {
// the case for (Serial.available() > 0) There's info on the serial line
character = Serial.read();
content.concat(character);
if (character == '\n') break; // Keep reading until newline
stepper.runSpeedToPosition();
}
}
}

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.

Arduino: Want to make something only print once

I was writing a script for the ardunio so that it would print how far away something was, and I was trying to make it so that if it was equal to the default length (when the script first started) it would not work, and if the distance between the two numbers is greater than 3 inches to print again. Not sure why it isn't working. At first I tried to make it so that it would not print, also, if it was the same as the last printed length, so if anyone could figure that out instead, that would be amazing. Also, sorry if I sound stressed, I've been working on this probably super-simple script for at least 3 hours now.
#include <Ping.h>
Ping ping = Ping(13,0,0);
int defaultlength = 0;
int length = 0;
int afterlength = 0;
void setup(){
Serial.begin(9600);
ping.fire();
defaultlength = ping.inches();
}
void loop(){
ping.fire();
length = ping.inches();
delay(100);
afterlength = length - defaultlength;
sqrt(afterlength^2);
if (afterlength >= 3) {
Serial.print(afterlength);
ping.fire();
Serial.print("Inches: ");
Serial.print(ping.inches());
Serial.print(" | Centimeters: ");
Serial.print(ping.centimeters());
Serial.print(" | Light: ");
if (analogRead(A0) >= 1000) {
Serial.print("ON");
Serial.println();
}
else {
Serial.print("OFF");
Serial.println();
}
}
delay(1000);
}
Also, It is not printing anything at all ever. I'm not sure if its not going through the loop or what.
Your line sqrt(afterlength^2); doesn't do anything useful. Did you mean to take the absolute value by writing
afterlength = sqrt(afterlength*afterlength);
The ^ operator is the bitwise XOR -- not at all what you were trying to do.
Does that make it better?
As for your other question:
"At first I tried to make it so that it would not print, also, if it was the same as the last printed length, so if anyone could figure that out instead, that would be amazing." - here is what you can do:
1) define another variable in the head of the script - call it lastlength and initialize it to defaultlength (right after you did your first ping in setup())
2) in the loop, change the if statement to
if ((afterlength >= 3) && (abs(length - lastlength) > 0.1)) {
3) finally, at the end of your if{} statement, add:
lastlength = length;
The reason to put that in the if{} block is to make sure that you only update it if things have changed sufficiently - otherwise, you keep the same "don't tell me again until it's different than the number you told me before" value. Of course, the > 0.1 value can be replaced with whatever tolerance you want. Note also use of abs() - a bit more compact than the square root of the square.

Resources