Arduino creating delay function - c

I am trying to make my own delay function. Briefly mydelay function is calling toggled function every secs seconds. The code is not well written, i know (this is the first version). But i am just trying to get it work properly. Then i will refactor it. But i have some unexpected bugs. First time the loop in x function is working properly. It is printing "I am in while" for 1 second and then it prints "Im ending mydelay" which is the behaviour i want. But after finishing the loop in x. The second time when it loops. It enters the mydelay function (that is ok). But then it is not printing "I am in while" at all. It just prints "Im ending mydelay" which is not good.
Here is the code:
#include <Arduino.h>
int led = 7;
void setup() {
Serial.begin(9600);
pinMode(led, OUTPUT);
}
void loop() {
x();
Serial.println("Im ending main loop");
}
void x() {
for (int i = 0; i <= 10; i++) {
mydelay(led, 0, 1);
mydelay(led, 1, 1);
}
}
void mydelay(int pin, int hol, int secs) {
int starttime = millis();
while ((millis() - starttime) <= (secs * 1000)) Serial.println("I am in while");
toggled(pin, hol);
Serial.println("Im ending mydelay");
}
void toggled(int pin, int hol) {
digitalWrite(led, hol);
}

Change int starttime = millis(); to unsigned long starttime = millis();. This might be the problem because if you are using an int, your program will go crazy after 32 seconds. That is a problem because an int can only hold a number going from -32,768 to 32,767 .
Also, you might as well try this:
while ((millis() - starttime) <= (secs * 1000))
{
Serial.println("I am in while");
}

maybe you can try to reset the millis using something like this, I don't have an arduino so it's not tested but hopefully it can help.
extern volatile unsigned long timer0_millis;
unsigned long reset = 0;
#include <Arduino.h>
int led = 7;
void setup() {
Serial.begin(9600);
pinMode(led, OUTPUT);
}
void loop(){
x();
Serial.println("Im ending main loop");
setMillis(reset);
}
void setMillis(unsigned long new_millis){
uint8_t oldSREG = SREG;
cli();
timer0_millis = new_millis;
SREG = oldSREG;
}
void x() {
for (int i = 0; i <= 10; i++) {
mydelay(led, 0, 1);
mydelay(led, 1, 1);
}
}
void mydelay(int pin, int hol, int secs) {
int starttime = millis();
while ((millis() - starttime) <= (secs * 1000)) Serial.println("I am in while");
toggled(pin, hol);
Serial.println("Im ending mydelay");
}
void toggled(int pin, int hol) {
digitalWrite(led, hol);
}

Related

Arduino Teensy array of Bounce not actually updating

Im quite new to Arduino and C itself, but I can't figure out why the array does not work, while the sanity check does.
It seems to me that both should operate fine. I'm guessing I'm missing some small bit of crucial info with regards to how arrays in C work.
The entirity of the code:
#include <Bounce2.h>
#define BUTTON_AMOUNT 1
#define DEBOUNCE_INTERVAL 25
const int ledPin = LED_BUILTIN;
//Bounce *buttons[BUTTON_AMOUNT];
Bounce buttons[BUTTON_AMOUNT];
Bounce b1 = Bounce();
void setup() {
Serial.begin(31250);
pinMode(ledPin, OUTPUT);
for (int i = 0; i < BUTTON_AMOUNT; i++) {
Bounce b = Bounce();
b.attach(i, INPUT_PULLUP);
b.interval(DEBOUNCE_INTERVAL);
buttons[i] = b;
// buttons[i] = new Bounce();
// (*buttons[i]).attach(i, INPUT_PULLUP);
// (*buttons[i]).interval(DEBOUNCE_INTERVAL);
}
b1.attach(0, INPUT_PULLUP);
b1.interval(25);
}
void loop () {
for (int i = 0; i < BUTTON_AMOUNT; i++) {
// Serial.println("looping ...");
Bounce b = buttons[i];
b.update();
if (b.rose()) {
// Serial.println("rising edge");
digitalWrite(ledPin, LOW);
}
if (b.fell()) {
// Serial.println("falling edge");
digitalWrite(ledPin, HIGH);
}
}
// sanity check
b1.update();
if (b1.rose()) {
Serial.println("B1 - rising edge");
digitalWrite(ledPin, LOW);
}
if (b1.fell()) {
Serial.println("B1 - falling edge");
digitalWrite(ledPin, HIGH);
}
}
Your are copying Bounce objects into and out of the button array. E.g.
...
for (int i = 0; i < BUTTON_AMOUNT; i++) {
Bounce b = Bounce();
b.attach(i, INPUT_PULLUP);
b.interval(DEBOUNCE_INTERVAL);
buttons[i] = b; // <- bitwise copy
...
However, since Bounce doesn't implement means for copying objects buttons[i] = b simply copies b bitwise into the array which won't work.
Instead of copying the elements out of / into the array you can simply access them. Here working code showing how to do that.
#include "Bounce2.h"
constexpr int BUTTON_AMOUNT = 5;
constexpr int DEBOUNCE_INTERVAL = 25;
constexpr int ledPin = LED_BUILTIN;
Bounce buttons[BUTTON_AMOUNT]; // this already constructs the buttons in the array, you can use them directly
void setup() {
pinMode(ledPin, OUTPUT);
for (int i = 0; i < BUTTON_AMOUNT; i++) {
buttons[i].attach(i, INPUT_PULLUP); // directly access the Bounce objects in the array
buttons[i].interval(DEBOUNCE_INTERVAL);
}
}
void loop () {
for (int i = 0; i < BUTTON_AMOUNT; i++) {
buttons[i].update();
if (buttons[i].rose()) {
Serial.printf("rising edge B%u\n", i);
digitalWrite(ledPin, LOW);
}
if (buttons[i].fell()) {
Serial.printf("falling edge B%u\n", i);
digitalWrite(ledPin, HIGH);
}
}
}

Arduino: detecting buttons pressed inside a while loop

I have been trying to write a code to basically add points to a score whenever I pressed a button while a certain amount of time is running down. The problem I am finding is that it doesn't detect when the button is pressed while the time is decreasing, in fact it can only detect when the time starts to decrease and then it doesn't matter at which state the button is it will continue to add to the score. Anyway here is the main code:
void loop() {
buttonState01 = digitalRead(button01);
buttonState02 = digitalRead(button02);
buttonState03 = digitalRead(button03);
if (buttonState01){
time = 3000;
while(time > 0){
if (buttonState02){
score += 10;
Serial.println(score);
}
time--;
Serial.println(time);
}
}
}
And here is the full code if needed:
int button01 = 4;
int button02 = 3;
int button03 = 2;
int buttonState01 = 0;
int buttonState02 = 0;
int buttonState03 = 0;
float time;
int score;
void setup() {
score = 0;
time = 0;
pinMode(button01, INPUT);
pinMode(button02, INPUT);
pinMode(button03, INPUT);
Serial.begin(9600);
}
void loop() {
buttonState01 = digitalRead(button01);
buttonState02 = digitalRead(button02);
buttonState03 = digitalRead(button03);
if (buttonState01){
time = 3000;
while(time > 0){
if (buttonState02){
Serial.println("Points");
}
time--;
Serial.println(time);
}
}
}
You should read the status of a button inside the while loop. Like this:
while(time > 0)
{
buttonState02 = digitalRead(button02);
if (buttonState02){
Serial.println("Points");
}
time--;
Serial.println(time);
}
And in your code, there is no logic to add points to the score.
A hardware interrupt would do exactly what you need.
Attach an interrupt routine to the pin your button is linked to, and get it to set the 'score' variable. Make sure you introduce some sort of timeout to avoid button-bounce (I.e. set LastTimeIncremented when you increase the score, and only increment score if LastTimeIncremented is more than 1 second ago)
This way the score will always be set regardless of what else the program may be doing.
Information on this can be found in the Arduino https://www.arduino.cc/en/Reference/attachInterrupt
The example on that page would do exactly what you want, just replace 'blink' with 'incrementScore' and you're pretty much done
const byte ledPin = 13;
const byte interruptPin = 2;
int score = 0;
int increment = 1;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), incScore, RISING);
}
void loop() {
digitalWrite(ledPin, state);
}
void incScore() {
score = score+increment;
// add anti-bounce functionality here
}

Arduino millis not work

I have written a huge program for Arduino.
I have tested each function individually, and all go fine except the function where I need millis().
Now carry the code block that I encounter any difficulties.
the variable T contains the number in seconds for this is multiplied by 1000
void onResistance(){
Input = sensors.getTempC(tempSensor);
sensors.requestTemperatures(); // prime the pump for the next one - but don't wait
digitalWrite(RelayPin, HIGH);
//more code
Input = sensors.getTempC(tempSensor);
sensors.requestTemperatures(); // prime the pump for the next one - but don't wait
if(Input<Setpoint){ onResistance(); }
else{ digitalWrite(RelayPin, LOW); istru++; return ; }
return ;
}
void statTemp(){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > ttemp){
previousMillis = currentMillis;
Input = sensors.getTempC(tempSensor);
sensors.requestTemperatures();
lcd.setCursor(0,1);
lcd.print(F("T. Att.:"));
lcd.print(Input);
lcd.write(1);
lcd.print(F("C"));
if (Input<Setpoint) {
digitalWrite(RelayPin, HIGH);
statTemp();
} else if(Input>Setpoint || Input == Setpoint) {
digitalWrite(RelayPin, LOW);
statTemp(); }
} else if(currentMillis - previousMillis < ttemp) { playShortBeep(); istru++; return; }
return ;
}
void startFan(){
Input = sensors.getTempC(tempSensor);
sensors.requestTemperatures(); // prime the pump for the next one - but don't wait
digitalWrite(FAN_PIN, HIGH);
//more code
Input = sensors.getTempC(tempSensor);
sensors.requestTemperatures(); // prime the pump for the next one - but don't wait
if(Input>Tm){ startFan(); }
else{ digitalWrite(FAN_PIN, LOW); istru++; return ; }
return ;
}
void controll(){
if(!start)
return ;
if(start){
if(istru==0){
onResistance();
}
if(istru==1){
ttemp = (T * 1000) + millis() ;
statTemp();
}
if(istru==2){
startFan();
}
if(istru==3){
start =false;
opState = OFF;
playShortBeep();
playShortBeep();
playShortBeep();
istru=0;
}
}
delay(100);
return ;
}
I need for the time T the function statTemp remains running conducting checks if written in it.
sorry for my bad english
So you want to stay in the function statTemp() until time T has passed?
Then something like this might work
void statTemp(){
unsigned long currentMillis;
unsigned long enteringMillis = millis();
while (((currentMillis = millis()) -enteringMillis) < T)
{
if(currentMillis - previousMillis > ttemp){
etc etc etc....
}
return ;
}
Notice the MIGHT. I don't know if millis is updated at every timer interrupt or just in the loop function; in the latter case, you will be stuck forever in the function.
Consequently i suggest you not to do this, but think at another approach: an FSM which handles the function to be executed. It's a cleaner way to proceed and less error-prone.
Bye
EDIT:
Here is a complete working example. In this example, the function myfunc is executed for 10 seconds; during this time the board performs some actions (in this example serial output). When 10 seconds pass, the program goes on, thus repeating the loop function.
unsigned long previousTime;
void myfunc();
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("I'm in the loop function");
myfunc();
}
void myfunc()
{
unsigned long currentTime;
unsigned long enteringTime = millis();
while(((currentTime = millis()) - enteringTime) < 10000)
{
if(currentTime - previousTime > 1000)
{
previousTime = currentTime;
Serial.println("I'm in the custom function");
}
}
}
HOWEVER my suggestion is still the same: instead of blocking the execution inside of a function, use a finite state machine; it's much more flexible and easier to understand, implement and edit.

Arduino - Variable should increment by 2nd variable - always equal to 2nd varaible only

The code below is part of a larger project. The intent is to flash an led with a variable on time, reset the on time and accumulate the total "on" time. The on time is changed each time the "on" period has elapsed.
Code below appears to successfully change the "on" time at the end of each "on" time period, but does not accumulate the total time.
I expected ledtime to equal LED_ON on the first pass (for example 1000) and then equal the previous ledtime + LED_ON (for example 1000 + 2538 = 3528) on the second pass etc.
Instead ledtime is always equal to the current LED_ON, so it appears ledtime is always set to zero on each pass, which I don't understand.
I'm new at arduino/C programming and suspect I'm missing something pretty simple/obvious, but have played with this for awhile with no resolution (including moving the ledtime = etc statements to various areas within the blink routine).
long ledtime;
const int LED_PIN = 13;
const int grnled = 11;
unsigned long LED_ON = 800; //milliseconds
int LED_OFF = 2000;
int redled = 10;
int yellowled = 12;
unsigned long ms; //time from millis()
unsigned long msLast;
unsigned long mslast2;//last time the LED changed state
boolean ledState; //current LED state
void setup(void)
{
pinMode(grnled, OUTPUT);
pinMode(redled,OUTPUT);
pinMode(yellowled,OUTPUT);
Serial.begin(9600);
}
void loop(void)
{
while(millis()<5000) {
digitalWrite(redled,HIGH);
digitalWrite(yellowled,LOW);
}
while (millis() >(5000) && millis()< 20000){
ms = millis();
blinkLED();
}
if (millis() > 20000 && millis() < 30000) {
digitalWrite(redled,HIGH);
}
if (millis() > 30000) {
digitalWrite(yellowled,HIGH);
digitalWrite(redled, LOW);
}
}
void blinkLED(void)
{
if (ms - msLast > (ledState ? LED_ON : LED_OFF)) {
digitalWrite(grnled, ledState = !ledState);
msLast = ms;
long ledtime = ledtime + LED_ON; //this does not work
Serial.println("ledtime = ");
Serial.println(ledtime);
if (ms-mslast2> LED_ON) {
LED_ON = random(500,5000); //this works
LED_OFF = 2000;
mslast2 = ms;
Serial.println("LED_ON = ");
Serial.println(LED_ON);
}
}
}
I'm not very sure of what you're trying to do, but with the line you commented, you create a local variable ledtime which has the same name of your global one. And because it's local to your function, it gets erased at the end of your function.
So first initialize ledtime at 0 at its declaration,
Then try to replace this line by
ledtime += LED_ON;

Confusing increment behaviour

int i = 1;
void setup() {
Serial.begin(9600);
}
void loop() {
if(i == 1){
Serial.print(i);
}
i++;
}
This is intended to only print the value of i once. Why does it keep printing 1 forever?
This code works properly only writing i once:
int i = 1;
void setup() {
Serial.begin(9600);
}
void loop() {
if(i == 1){
Serial.print(i);
}
i = 2;
}
Assuming loop() is called in a loop:
i will overflow in the first example.
In the second example it is fixed to the value of 2 after the first iteration.
You may also want to add some delay because sometimes you can miss the first Serial.println();.
Something like that:
int i = 1;
void setup() {
Serial.begin(9600);
delay(1000); //wait for one second
}
Hope it helps!
If you want your first example to work longer. Change "int" to "long".
int can only store 2 bytes. -32,768 to 32,767. You will reach this number really fast.
long can store 4 bytes. -2,147,483,648 to 2,147,483,647. This will take a whiiiile.

Resources