Delay within a timer (what is the correct approach) - c

I'm in a pickle regarding concepts relating to timers. How can I can I operate a "delay" inside a timer? This is the best way I can frame the question knowing full well what I'm trying to do is nonsense. The objective is: I wish to test the pinState condition 2 times (once initially and then 4 seconds later) but this all needs to happen periodically (hence a timer).
The platform is NodeMCU running a WiFi (ESP8266 chip) and coding done inside Arduino IDE.
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
BlynkTimer timer;
char auth[] = "x"; //Auth code sent via Email
char ssid[] = "x"; //Wifi name
char pass[] = "x"; //Wifi Password
int flag=0;
void notifyOnFire()
{
int pinState = digitalRead(D1);
if (pinState==0 && flag==0) {
delay(4000);
int pinStateAgain = digitalRead(D1);
if (pinStateAgain==0) {
Serial.println("Alarm has gone off");
Blynk.notify("House Alarm!!!");
flag=1;
}
}
else if (pinState==1)
{
flag=0;
}
}
void setup()
{
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
pinMode(D1,INPUT_PULLUP);
timer.setInterval(1000L,notifyOnFire);
}
void loop()
{
//Serial.println(WiFi.localIP());
Blynk.run();
timer.run();
}

an easy fix would be to set the periodicity of the timer to be 4000L timer.setInterval(4000L,notifyOnFire); and in notifyOnFire use a static variable and toggle its value whenever notifyOnFire is called
void notifyOnFire()
{
static char state = 0;
if( state == 0)
{
/* Write here the code you need to be executed before the 4 sec delay */
state = 1;
}
else
{
/* Write here the code you need to be executed after the 4 sec delay */
state = 0;
}
}
The nice thing about static variables is that they are initialized only once at compile time and they retain their values after the scope of code changes (In this case function notifyOnFire exits).

Related

The ISR executed once even when the event not happened

I am using PIC24FJ128GA204 microcontroller in PIC24F Curiosity Development Board.
The ISR is executed at least once even when the event not happened.
Here is the code:
#include <xc.h>
int Random_mode_condition=0;
void __attribute__((__interrupt__, __shadow__)) _INT1Interrupt(void) {
Random_mode_condition = 44;
_INT1IF = 0;
}
void RC9_Switch_Config() {
_TRISC9 = 1; // Switch input
RPINR0bits.INT1R = 25;
IFS1bits.INT1IF=0;//Clear the interrupt flag
IPC5bits.INT1IP1=1;//Choose a priority
INTCON2bits.INT1EP=0;//rising edge
IEC1bits.INT1IE=1;//enable INT1 interrupt
}
int main() {
LATC=0x0000;
RC9_Switch_Config();
while(1){
if(Random_mode_condition==44){ TRISC=0x0000; LATC=0xffff;}
}
return 0;
}
Random_mode_condition will equal 44 then the if statement will be executed.
Please help

Global variable being reset after each call

In my project I'm using a global variable but it's not working as expected because it is initialized everytime it's executed and honestly I don't know what could be going on.
The variable is cookingSignalReceived.
The program is structured as follows:
//File Controller.c:
while (1)
{
Controller_Run_State_Machine();
}
void Controller_Run_State_Machine(void)
{
/* start of activity code */
Inputs_ReadSensors();
Comms_CheckReceivedData();
Controller_UpdateSTM();
}
The problem is inside Comms file:
//File Comms.c
uint8_t cookingSignalReceived = 0;
void Comms_CheckReceivedData(void)
{
/* start of activity code */
uint8_t uartDataAvailable = Comms_R_UART0_checkIfDataAvailable();
if (uartDataAvailable == 1)
{
Comms_ParseReceivedCommand();
}
}
void Comms_ParseReceivedCommand(void)
{
/* start of activity code */
/* UserCode{499E2AA6-1F61-4753-9221-77F85E7B5D92}:YjMeKqu95e */
uint8_t CRC_check_OK = 0;
uint8_t* buffer;
/* UserCode{499E2AA6-1F61-4753-9221-77F85E7B5D92} */
Comms_R_UART0_resetFlag_dataAvailable();
buffer = Comms_R_UART0_getBuffer();
CRC_check_OK = Comms_crcCheck(buffer);
if (CRC_check_OK == 1)
{
Comms_processMessage(buffer); //<-- Variable is used in this function
}
}
Global variable is used inside Comms_processMessage(). The issue is that every time that the function is called, the global variable is set to the initial value. Do you find anything strange here?
EDITED:
void Comms_processMessage(uint8_t* buffer)
{
/* UserCode{BCB3B791-2DF9-492b-B53B-6FEB24BD8F77}:eyCoSfmCKb */
uint8_t message = buffer[0];
uint8_t param1 = buffer[1];
uint8_t param2 = buffer[2];
//---------------------------------------------------------------------
// START COOKING 1ST STEP REQUEST
//---------------------------------------------------------------------
if (message == MSG_COOK_1ST && param1 == START_PARAM)
{
// Wait for second frame
cookingSignalReceived = 1;
#ifdef DEBUG
R_UART0_Send("Cook 1st step!!", sizeof(char) * 15);
#endif
}
//---------------------------------------------------------------------
// START COOKING 2ND STEP REQUEST
//---------------------------------------------------------------------
else if (message == MSG_COOK_2ND && param1 == START_PARAM)
{
// Wait for second frame
if (cookingSignalReceived == 1)
{
Controller_signalsBufferEnqueue(cookingSignal);
}
#ifdef DEBUG
R_UART0_Send("Cook 2nd step!!", sizeof(char) * 15);
#endif
}
}
Note that my original idea was to use a local static variable but I was having the same issue so I tried with a global variable.
In certain cases the MCUs restart because unrecoverable errors or bad hardware settings. This should be the problem! A cause of this MCUs behaviour may be also bad pointers management.

Granting access with RFID card

I've got a problem with my arduino program. I'm using a RFID reader to scan cards (this part works flawlessly). I want the program to grant access to using some buttons (doesn't matter to be honest). The user who uses a verified card can use the functionalities until he scans a card again. I've deleted some unnecessary parts of the code.
#include <SPI.h>
#include <MFRC522.h>
String read_rfid;
String ok_rfid_1="a3f90f7"; //ID of the verified CARD
const int buzzer=8; //Buzzer
const int redLed=7;
const int greenLed=6;
const int yellowLed=5;
byte access=false; //
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
}
/*
* Helper routine to dump a byte array as hex values to Serial.
*/
void dump_byte_array(byte *buffer, byte bufferSize) {
read_rfid="";
for (byte i = 0; i < bufferSize; i++) {
read_rfid=read_rfid + String(buffer[i], HEX);
}
}
void granted() { } //it lights up the green led
void denied() { } //it lights up the red led
void login() {
if (read_rfid==ok_rfid_1) {
granted();
access=true;
} else {
denied();
}
delay(1000);
}
void logout() {
if (read_rfid==ok_rfid_1 && access==1) {
access=false;
Serial.println("Logout ");
}
}
void loop() {
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent())
return;
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())
return;
dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
Serial.println(read_rfid);
login();
while(access==true)
{logout();};
}
The logging in part works well, but it logs out automatically. As I observed the problem might be that if(read_rfid==ok_rfid_1 && access==1) is always true, because the read_rfid does not change. Do you have any ideas to solve my dillema?

in this both the function why it is require to do WATCHDOG_RESET()?

void NS16550_putc(NS16550_t com_port, char c)
{
while ((serial_in(&com_port->lsr) & UART_LSR_THRE) == 0);
//write to the THR
serial_out(c, &com_port->thr);
if (c == '\n')
//why do we require to call this watch dog reset
WATCHDOG_RESET();
}
char NS16550_getc(NS16550_t com_port)
{
while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) {
#ifdef CONFIG_USB_TTY
extern void usbtty_poll(void);
usbtty_poll();
#endif
//why do we require to call this watch dog reset
WATCHDOG_RESET();
}
//return the rbr value
return serial_in(&com_port->rbr);
}
I don't know the context of this code.
But most likely it's because you don't want your operation to last so long that the watchdog times out (and resets your device...)
for example,
while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) {
#ifdef CONFIG_USB_TTY
extern void usbtty_poll(void);
usbtty_poll();
#endif
//why do we require to call this watch dog reset
WATCHDOG_RESET();
}
In the above code, you're validating some condition repeatedly in this while loop, now this loop may run for a long time and if you don't reset your watchdog timer (or kick your watchdog), the watchdog'll likely time out eventually.

Move robot set number of steps (Arduino)

I want to move my robot a set number of steps and then have it stop. However the loop just seems to run on infinitely. Is there a mistake in the way that I am using void loop() or perhaps in the way that I have written my 'for' loop?
// walkerForward.pde - Two servo walker. Forward.
// (c) Kimmo Karvinen & Tero Karvinen http://BotBook.com
// updated - Joe Saavedra, 2010
#include <Servo.h>
Servo frontServo;
Servo rearServo;
int centerPos = 90;
int frontRightUp = 75;
int frontLeftUp = 120;
int backRightForward = 45;
int backLeftForward = 135;
void moveForward(int steps)
{
for (int x = steps; steps > 0; steps--) {
frontServo.write(centerPos);
rearServo.write(centerPos);
delay(100);
frontServo.write(frontRightUp);
rearServo.write(backLeftForward);
delay(100);
frontServo.write(centerPos);
rearServo.write(centerPos);
delay(100);
frontServo.write(frontLeftUp);
rearServo.write(backRightForward);
delay(100);
}
}
void setup()
{
frontServo.attach(2);
rearServo.attach(3);
}
void loop()
{
moveForward(5);
}
the loop() function is executed within an infinite loop (if you check the main cpp file that ships with the Arduino IDE, you'll see something like this:
int main()
{
setup();
for (;;) {
loop();
}
return 0;
}
So either put the call to your moveForward() function to setup() and make loop() an empty function, or call exit(0); from within loop() after moveForward(). The first approach looks like this:
void setup()
{
frontServo.attach(2);
rearServo.attach(3);
moveForward(5);
}
void loop()
{
}
And the second one looks like this:
void setup()
{
frontServo.attach(2);
rearServo.attach(3);
}
void loop()
{
moveForward(5);
exit(0);
}
Since you probably will want to eventually do more than move the robot just 5 steps, I'd suggest using a variable flag to hold the robot state. It only executes the movement routine when the flag has been set to true.
If you are using serial, when a move command is received (and the number of steps, direction perhaps?) you set the flag to true and then issue the move command. If you are using sensors or buttons, the same logic applies.
You will need some logic to handle an incoming movement command while a movement is occurring (though with your tight movement loop you actually won't be able to respond to incoming commands unless you use interrupts - but you want to consider this sort of thing if you are planning to build out a full movement bit of firmware).
boolean shouldMove;
void setup()
{
shouldMove = true;//set the flag
}
void loop()
{
if (shouldMove){
moveForward(5);
}
}
void moveForward(int steps)
{
shouldMove = false; //clear the flag
for (int x = steps; steps > 0; steps--) {
// tight loop controlling movement
}
}
}

Resources