I have a program which constantly polls the serial port waiting for data which gets sent every second from a windows application.
it then buffers the data from the serial into block of 3 characters.
First recorded value is value1, i then want to record it again as value2, 3 mins later, without stopping the rest of the program working.
Here's my code, without any timers.
void loop()
{
GetAz();
}
void GetAz(){
int x = 0;
while (x < 4){
x++;
if( Serial.available())
{
char ch = Serial.read();
if(index < MAX_LEN && ch != 13) // 13 is ascii value of carriage return
{
strValue[index++] = ch; // add the ASCII character to the string;
}
else
{
// here when buffer full or on the first non digit
strValue[index] = 0; // terminate the string with a 0
//int value = atof(strValue); // use atof to convert the string to a float
index = 0; // reset the index for the next string
lcd.setCursor(10,3);
Serial.println(strValue);
lcd.print(strValue);
}
}
}
int value1 = atoi(strValue);
}
In GetAz, you have a while loop. The while loop terminates when x gets to be 4. What is the purpose of x?
GetAz returns after 4 checks to see whether there was data available to be read, regardless of whether or not there was data.
At most you will get 4 bytes in strValue, which you show on the LCD, as you are building the not-properly-NULL-terminated string.
At the end of GetAz, you store the integer value of the possibly-not-NULL-terminated string in a local variable that immediately goes out of scope, and is, therefore, lost.
There may be more problems, but those occur to me right off the bat.
So, what is it you are trying to accomplish? You aren't doing anything with time, so the time-related aspect of your initial question do not seem to have an answer.
If you are trying to create an array that holds no more than 3 integers, and each call to GetAz puts the value it gets into one of the positions in that array, then GetAz needs to do some of the work (getting the value), and loop needs to do some (putting it in the array in the right place.
Use the millis() function to get the time when there is serial data available. Store the result in a global variable called previousMillis. Collect the serial data as you are doing now, in the if block. (I don't know what the while block is doing.)
Change GetAz to return an int. Store that int, in loop.
Also in loop, check to see if millis() - previousMillis is greater than the desired delay. If it is, call GetAz again, and store the results in another variable (or the next position in an array).
I'll take a look at the millis() function when i get home tonight. I've already removed the "while" statement as i realized that the serial termination was controlled by the carrige return.
to store an int in the GetAz loop i was thinking of using
int value = atoi(strValue); which should do the trick.
I'll probably be back later for some help on the millis fucntion.
There is a example program in the digital section of the Arduino IDE:
/* Blink without Delay
Turns on and off a light emitting diode(LED) connected to a digital
pin, without using the delay() function. This means that other code
can run at the same time without being interrupted by the LED code.
The circuit:
* LED attached from pin 13 to ground.
* Note: on most Arduinos, there is already an LED on the board
that's attached to pin 13, so no hardware is needed for this example.
created 2005
by David A. Mellis
modified 17 Jun 2009
by Tom Igoe
http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/
// constants won't change. Used here to
// set pin numbers:
const int ledPin = 13; // the number of the LED pin
// Variables will change:
int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated
// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000; // interval at which to blink (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}
void loop()
{
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, is the difference
// between the current time and last time we blinked the LED bigger than
// the interval at which we want to blink the LED.
if (millis() - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = millis();
// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}
This is a quite interesting library that helps you to make delays without stopping the processor. It just processes millis(). It's very simple to use it just looking at the examples.
Paul you mentioned storing the serial data into as an int value.
Change GetAz to return an int. Store that int, in loop.
I'm having some problems storing the array of 3 characters as a Int value. I thought just doing some sort of conversion might work.
void GetAz(){
if( Serial.available())
{
char ch = Serial.read();
if(index < MAX_LEN && ch != 13) // 13 is ascii value of carriage return
{
strValue[index++] = ch; // add the ASCII character to the string;
}
else
{
// here when buffer full or on the first non digit
strValue[index] = 0; // terminate the string with a 0
int value = atoi(strValue); // use atoi to convert the string to int
index = 0; // reset the index for the next string
lcd.setCursor(10,3);
Serial.println(strValue);
lcd.print(strValue);
}
}
}
I figure i could just use this line of code to do the conversion but it just hangs up the whole process.
int value = atoi(strValue);
Anyone got any other idea's of how to convert an array to an int value ?
It's hard to say what the problem is without any idea what data you are reading from the serial port. Show us the serial monitor data, and we can make better recommendations.
One thing I see, though, is that you are not NULL terminating the string. atoi is looking for the NULL, to know where to stop reading the array of characters.
the serial data is simply 3 numbers sent to the serial port from a windows application every second.
e.g. 356
from my code if i just do a lcd.print(strValue); i see the correct value being displayed and updated.
Sorry i forgot to post thati have the follow defined globally at the beginning of my code.
const int MAX_LEN = 3; // the max digits
char strValue[MAX_LEN + 1]; // add one for the terminating null
So i thought that along with this line in my function, would terminate properly.
if(index < MAX_LEN && ch != 13) // 13 is ascii value of carriage return
The whole code is as follows
const int MAX_LEN = 3; // the max digits in the number plus decimal point
char strValue[MAX_LEN + 1]; // add one for the terminating null
int index = 0;
void loop()
{
millis();
GetAz();
ButtonPress();
llegirPos();
delay(100);
}
void GetAz(){
if( Serial.available())
{
char ch = Serial.read();
if(index < MAX_LEN && ch != 13) // 13 is ascii value of carriage return
{
strValue[index++] = ch; // add the ASCII character to the string;
}
else
{
// here when buffer full or on the first non digit
strValue[index] = 0; // terminate the string with a 0
int value = atoi(strValue); // use atof to convert the string to a float
index = 0; // reset the index for the next string
lcd.setCursor(10,3);
Serial.println(strValue);
lcd.print(strValue);
}
}
}