UKHeliBob:
HINT : Post an example program that exhibits the problem
You really should know better after 333 previous posts
By the way, there is no such thing as an if loop
Right
This is Robin2's example 5 program from his Serial Tutorial that I am modifying to test HC12 modules.
I want to detect single string transmissions (and later also compare current and previous transmitted values).
A digital output has to go HIGH when a Receive is in Progress, and stay lit for say 1 second. Just single transmission bursts take place.
Here is void recWithStartEndMarkers(), I already included the DigitalWrite..
You did not use the millis() function correctly, but without any code I cannot help.
By the way, there is no such thing as an "if" loop. "if" does not loop. "if" is a statement.
I use the millis() function all of the time. The basic idea is to use millis() to note the time that something happened (like setting A to HIGH) and then checking each time through the loop() function to see if it is time to do something else (like setting A to LOW). All variables having to do with time should be unsigned long (or const unsigned long), the only arithmetic on the unsigned long variables should be subtraction, and the delay(...) function should not be used.
I cannot see how you have used/abused the loop() function so it is hard to help further. Nick Gammon has a web site with handy information on this topic but I do not currently have the URL.
vaj4088:
You did not use the millis() function correctly, but without any code I cannot help.
By the way, there is no such thing as an "if" loop. "if" does not loop. "if" is a statement.
I use the millis() function all of the time. The basic idea is to use millis() to note the time that something happened (like setting A to HIGH) and then checking each time through the loop() function to see if it is time to do something else (like setting A to LOW). All variables having to do with time should be unsigned long (or const unsigned long), the only arithmetic on the unsigned long variables should be subtraction, and the delay(...) function should not be used.
I cannot see how you have used/abused the loop() function so it is hard to help further. Nick Gammon has a web site with handy information on this topic but I do not currently have the URL.
I know the url of Nick Gammon's site; I will look at it more in depth.
The code I used is in my previous post.
I use the millis() as follows, please correct me if wrong:
//..
int interval = 1000; //1 second interval
unsigned long currentMillis = millis();
//..do something A..
if (currentMillis - previousMillis >= interval) {
//..do something B.. This something B will always be executed the first time, and then only after interval
previousMillis = currentMillis();
}
The result of this code is that B will be exectued as soon as the if statement is reached, and then only again after interval.
My issue is that I need this statement B only executed after interval.
I.e.: a "while" loop is executed during which a digital output is set HIGH. After the while is done, then only after a fixed time does the digital output need to go LOW.
gfvalvo:
It would really help to see a complete sketch. Then it's much easier to understand the context, see how variables are declared / defined, etc.
I am sorry, I misunderstood UKHeliBob too who asked the same; I thought it would be easier to read anything besides the actual void was not included.
Meanwhile I did write a millis() delay code for the digital output delayed off starting line 110. But it is not right.
// http://forum.arduino.cc/index.php?topic=499210.msg3407044#msg3407044
// http://forum.arduino.cc/index.php?topic=396450.0
// HC12 Communication between Arduinos
/*
This program serves to send one integer (or byte) only from two different HC12
transmitters at one sensor each (A and B)to one HC12 receiver at the central
controller Arduino. The receiving HC12 has to know from which transmitter A or B
the value comes.
The data are sent with start- and endmarkers
v5: two integers used, one for the sensor value (integer1FromPC) and one
for the sensor identifier (integer2FromPC). At the transmitter the sensor A or B are
identiefied by reading two digital inputs connected to a dipswitch with
2 switches (max: 4 different sensor/transmitters).
// RECEIVER PART
*/
#include <SoftwareSerial.h>
const byte HC12RxdPin = 4; // Recieve Pin on HC12
const byte HC12TxdPin = 5; // Transmit Pin on HC12
SoftwareSerial HC12(HC12TxdPin, HC12RxdPin); // Create Software Serial Port
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
// variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integer1FromPC = 0;
int integer2FromPC = 0;
int previousinteger1FromPC = 0;
int previousinteger2FromPC = 0;
float floatFromPC = 0.0;
boolean newData = false;
//============
void setup()
{
Serial.begin(9600);
HC12.begin(9600); // Open serial port to HC12
// declare pin 11 & 12 as output
pinMode (10, OUTPUT);
pinMode (11, OUTPUT);
pinMode (12, OUTPUT);
delay(100);
}
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
useParsedData();
newData = false;
}
}
//============
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
unsigned long previousMillis = 0; // timer
const int interval = 1000;
boolean rxStatus = false;
boolean ledState = false;
digitalWrite (12, LOW);
unsigned long currentMillis = millis();
while (HC12.available() > 0 && newData == false) {
rc = HC12.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
digitalWrite(12, HIGH);
previousMillis = currentMillis;
previousinteger1FromPC = integer1FromPC;
}
}
if (digitalRead(12) == HIGH) {
if (currentMillis - previousMillis >= interval) {
digitalWrite(12, LOW);
previousMillis = currentMillis;
}
}
}
//============
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index. It creates the variable
// strkIndx as a pointer to a variable of type char. It can hold the address of a
// variable of type char.
/*
strtokIndx = strtok(tempChars, ","); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integer1FromPC = atoi(strtokIndx); // convert this part to an integer
/*
strtokIndx = strtok(NULL, ",");
floatFromPC = atof(strtokIndx); // convert this part to a float
*/
strtokIndx = strtok(tempChars, ","); // get the first part - the string
integer1FromPC = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integer2FromPC = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
}
//============
void useParsedData() {
if (messageFromPC[0] == 'A') analogWrite (10, integer1FromPC);
if (messageFromPC[0] == 'B') analogWrite (11, integer2FromPC);
}
As it is now, previousMillis is an automatic variable local to recvWithStartEndMarkers(). Every time that function is entered previousMillis will be reset to 0. You don't want that. You want previousMillis to hold the millis() value from the instant you set output 12 to HIGH. Static will make that happen.
In the setup() function, you need to initialize previousMillis. For example:
previousMillis = millis() ;
If you only provide snippets of code, then you cannot expect more than snippets of answers. We like to see complete programs including setup and loop. Otherwise, important pieces of information get left out. I see this post as an example because I cannot see how or even if this variable got initialized.
vaj4088:
In the setup() function, you need to initialize previousMillis. For example:
previousMillis = millis() ;
If you only provide snippets of code, then you cannot expect more than snippets of answers. We like to see complete programs including setup and loop. Otherwise, important pieces of information get left out. I see this post as an example because I cannot see how or even if this variable got initialized.
Agreed, but in post #6 you can find the complete code
gfvalvo:
Said another way, static gives you the persistence of a global with the scope of a local.
So, if I understand correctly, if like in my case I have a program with 2 functions, and if I use a constant variable, then that constant variable does not keep its value?
So, if I understand correctly, if like in my case I have a program with 2 functions, and if I use a constant variable, then that constant variable does not keep its value?
I don't think you do understand correctly. You have variables declared locally within a function recvWithStartEndMarkers(). Without typing them as static, the local variables do not retain their value each time the function is called, but are reinitialized each time. Notice how Robin2 has declared some variables in the function as static.
Here's an examples of blinkWithoutDelay as it is normally shown with global variables, and a version with a function call. See how the previousMillis and ledState variables need to be static in order to keep their last value each time the function is called in loop().
void setup() {}
void loop()
{
blinkWithOutDelay(1000);
}
void blinkWithOutDelay(const unsigned long interval)
{
const byte ledPin = LED_BUILTIN;// the number of the LED pin
pinMode(ledPin, OUTPUT);
static byte ledState = LOW; // ledState used to set the LED
//byte ledState = LOW;
static unsigned long previousMillis = 0;
//unsigned long previousMillis = 0;
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
}
const byte ledPin = LED_BUILTIN;// the number of the LED pin
byte ledState = LOW; // ledState used to set the LED
unsigned long previousMillis = 0;
const unsigned long interval = 1000; // interval at which to blink (milliseconds)
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
}