Using an interrupt to handle a boolean in arduino - arduino

I've researched a bit, and I've ran into a couple of examples of how buttons are used as interrupts. However, the design I'm trying to implement uses analog sensors. Right now, what I want to do is to have my analog sensors flag a boolean to tell the interrupt to execute, not a button. How would I do so?
This is what I have thought up based on what I researched:
boolean isWall;
attachInterrupt(isWall, interruptFunction, RISING);
void loop() {
if(analogSensor.response > 450) {
isWall = true;
}
normalExecution(); // what it normally does if isWall is false
}
void interruptFunction() {
// code implementation
isWall = false; // set isWall back to false after executing interruptFunction
}
void normalExecution() {
// foo
}
Can someone verify?

Perhaps I am completely wrong but it has always been my understanding that interrupts in Arduino are based on the voltage seen by a pin - i.e. they are hardware interrupts. Consequently, while your code is correct for a hardware interrupt, it will not work for a change in a variable.
That said, this link and this link discuss Analog Comparator methods for accomplishing what you are trying to do.

Related

Can't figure out how or why this code solves an error. ESP32 arduino IDE with platform dot io

I am fairly new to coding and especially to C++ but usually with enough googling and breaking problems down to simpler blocks I can figure things out. This issue makes no sense to me though and the solution I just happened to come up with on accident makes even less sense to me.
I am writing a program for ESP32-S in vscode with platformio and broke this down to isolate what was causing the error and found this issue with class/object declaration:
This code will compile but I get a link error twice that says
undefined reference to `point::point()'
#include <Arduino.h>
class point {
public:
point();
point(uint day){
this->_day = day;
}
uint _day;
};
class channel {
public:
channel(String _color, byte _pin){
}
point _points[64];
};
channel red("red", 0);
void setup() {}
void loop() {}
Meanwhile this code with one seemingly unrelated change compiles and links without issue:
#include <Arduino.h>
class point {
public:
point();
point(uint day){
this->_day = day;
}
uint _day;
};
class channel {
public:
channel(){ // <--- Removing the arguments from channel constructor fixes it?
}
point _points[64];
};
channel red(); // <--- And here of course
void setup() {}
void loop() {}
I don't know why that fixes it, and I have a workaround for now if this is what I have to do, but I want to understand. Thanks.
You've declared a constructor point::point(), but not defined it (i.e. it has no body). This is not OK with the linker and that's what you're being told.
There are three ways to fix this.
Don't declare the constructor (compiler generates a default constructor which may or may not initialize the member _day to 0, depending on compiler and platform). Note that you also have the interesting alternative of deleting the default constructor.
Declare and define it to do whatever you consider appropriate.
Give your constructor point::point(uint day) a default argument value, e.g.: point::point(uint day = 0).
Side note on C style arrays of C++ objects like here:
point _points[64];
This is a dangerous combination, unless you know exactly what you're doing. See the C++ FAQ

Interrupts not working with Ethernet enabled

I am developing an application on a Nucleo-144 STM32F439ZI development board (product page, manual) and ran into an issue with hardware interrupts.
The reason I am posting this here instead of the electronic engineering site is that it seems to be a software problem related to the Arduino SDK rather than a hardware problem.
Anyway, when ethernet is off, the code below works meaning the interrupt routine gets triggered:
void setup(){
// ...
// set the user button pin as input
pinMode(PC13, INPUT_PULLDOWN);
// attach an interrupt
attachInterrupt(digitalPinToInterrupt(PC13), interruptHandler, RISING);
// ...
}
The interruptHandler function toggles a led, 3 lines of code. The PB7 pin is set as output within setup().
void interruptHandler(){
digitalWrite(PB7, HIGH);
delay(1000);
digitalWrite(PB7, LOW);
}
However, when using ethernet, it does not:
void setup(){
// ...
// set the user button pin as input
pinMode(PC13, INPUT_PULLDOWN);
//attach an interrupt
attachInterrupt(digitalPinToInterrupt(PC13), interruptHandler, RISING);
// mac and IP are unique on the network
Ethernet.begin(mac, ip);
// give the stack some time to do its business
delay(1000);
// ...
}
In this scenario pressing the button doesn't do anything, the interruptHandler no longer gets triggered.
I'd very much like to use interrupts rather than polling pins.
Am I doing something wrong?

Get UID from NFC Card on ESP32

I am having a bit of trouble reading an NFC card with an ESP32 (using Arduino IDE). I'm using PN532 module, which works pretty well. So far my code looks like:
#include <SPI.h>
#include <PN532_SPI.h>
#include <PN532.h>
#include <NfcAdapter.h>
PN532_SPI pn532spi(SPI, SS);
NfcAdapter nfc = NfcAdapter(pn532spi);
void setup(void) {
Serial.begin(115200);
Serial.println("NDEF Reader");
nfc.begin();
}
void loop(void) {
//Serial.println("\nScan a NFC tag\n");
if (! nfc.tagPresent())
{
return;}
else{
NfcTag tag = nfc.read();
String scannedUID = tag.getUidString();
Serial.println(scannedUID);
}
delay(5000);
}
which is basically just the example from don's ndef library. I just got the UID string, rather than printing all details of the card.
It does work and displays the UID. However, I get a message saying "Tag is not NDEF formatted". Which I don't really care about. I only want to print the UID to serial and then pick this up in a C# windows app. I guess I could just ignore it, but is there a way to stop it showing up?
Is there a better library I should be using?
Thanks
Andrew
I fixed it by modifying the mifareclassic.cpp file which is part of the library. I just commented out the offending line. Probably a better way since it's still doing the check. But will do for now.
Thanks
Andrew

Unexpected behavior when using freeRTOS with two tasks

I am using MPU9250-breakout board with Arduino Uno.
The library I used is from here.
Below is my code.
#include <Arduino_FreeRTOS.h>
#include "mpu9250.h"
MPU9250 IMU(Wire,0x68);
int status;
void task_1(void *pvParameters)
{
(void) pvParameters;
for (;;)
{
}
}
void task_2(void *pvParameters)
{
(void) pvParameters;
for (;;)
{
}
}
void setup() {
Serial.begin(115200);
while(!Serial) {}
status = IMU.begin();
if (status < 0) {
Serial.println("IMU initialization unsuccessful");
Serial.println("Check IMU wiring or try cycling power");
Serial.print("Status: ");
Serial.println(status);
while(1) {}
}
xTaskCreate(
task_2,
(const portCHAR *)"task2", // A name just for humans
128, // Stack size
NULL,
1, // priority
NULL);
xTaskCreate(
task_1,
(const portCHAR *)"task1", // A name just for humans
128, // Stack size
NULL,
1, // priority
NULL);
}
void loop()
{
}
The problem is that when there are two tasks defined, the program will be restarted automatically. But when I comment out task_1, the program works fine. The result value of xTaskCreate is correct.
I guess the problem might be the stack or heap size is too small, but I've increased stack and heap size and it's still doesn't work.
Can anyone tell me where the problem might be from?
At the end of your setup(), you need to start the scheduler:
// Now the task scheduler, which takes over control of scheduling individual tasks, //is automatically started.
vTaskStartScheduler();
That is all I see different between my project which works and yours.
Once you have created your tasks, you have to start scheduler.
Call vTaskStartScheduler() before exiting setup function and after you have created your tasks.
https://www.freertos.org/a00132.html
Just for the info, Arduino-UNO (with ATMega-328P) has very limited RAM and it may happen some tasks won't be created. Check return value of xTaskCreate functions.
When I run into this problem, it's usually been that my interrupt vectors weren't pointing to appropriate handlers. So when the RTOS needed to do a context switch, for example, it jumped off into la-la land. Since you say that taking out the tasks allows it to run to the library call, but fails in the same way, it is possible none of your handlers are setup correctly.
The FreeRTOS website has an FAQ about getting new projects to run that I would suggest reading through to help troubleshoot this kind of problem:
https://www.freertos.org/FAQHelp.html#faq
You might also look at some of the other AVR examples included with FreeRTOS to see how they have interrupts setup: https://www.freertos.org/a00090.html#ATMEL

Arduino Uno, multiple processes, multi-threading

I´m facing a problem with an application in Arduino Uno.
The board has a sensor that its counting products every second, after some time it sends the number of products to the server however this process takes more than a second, so the code that it is registering the products is not called until this process is completed so a piece of product sometimes is not counted.
I´ve been looking if Arduino supports multi-threading in order to have a thread for sending data to the server and the other one for registering the number of products, but i have no clear answer so far.
What would be the best solution to face this problem?
const long MAX_ITERATION = 100000;
const int OFF = 1;
const int ON = 0;
const int PHOTOELECTRIC_SENSOR = 3;
int counter = 0;
long iteration = 0;
int state = OFF;
void loop() {
registerProduct();
if (iteration >= MAX_ITERATION) {
// this process takes more than a second
sendDataToServer();
iteration = 0;
}
iteration++;
}
void registerProduct() {
int currentSensorState = digitalRead(PHOTOELECTRIC_SENSOR);
if (currentSensorState != state) {
if (currentSensorState == ON) {
counter++;
}
}
state = currentSensorState;
}
void sendDataToServer() {
// Sends data through HTTP protocol, and sets counter to zero
}
It looks like you might want to redesign this. While you might want to use something like threading on a desktop platform you don't have any hardware support for concurrency in that manner on the Arduino UNO. You do however have interrupts which you can use for your current problem.
Put the sensor on a pin change interrupt. Increment the counter in the ISR for that pin change interrupt. Arduino UNO has a few general purpose pin change interrupts, look at the datasheet for more info.
Then create a timer by using one of the internal timers. Attach this to an interrupt, when the timer interrupt fires take the counter amount and then put this aside. You will need to then send that value over to the server. Try to make the send not block. You may need to service the send in the main loop over multiple loop cycles.
By using the interrupts, especially the timing ones, you will free up a lot of processor cycles. Try to keep the amount of code in each of the ISRs as minimal as possible so that you don't lose data from interrupts being missed.
There is no concurrency in the microcontroller hardware or the language.
The correct way to do this is use an interrupt to accept the updates form the sensor asynchronously.
You should also not block on the send, you should send a few bytes and then send a few more on every loop through.
Using interrupts would be the preferred method, but you can also get away with using a simple or timed scheduler.
I've been working on a project that required one a while ago and you can find the source code here. It's based on a more extensive queuing library by Zuph called AVRQueue.
A simple implementation of the Scheduler library. I originally wrote it to be compiled with an avr-c compiler and haven't testing it with the arduino IDE but it shouldn't be an issue.
Scheduler m();
void setup() {
m.addTask(querySensor, "q_sens", 0, 1000);
m.addTask(doStuffWithData, "stuff", 0, 5000);
}
void loop() {
m.run(millis());
}
int querySensor(unsigned long now) {
...
}
int doStuffWithData(unsigned long now) {
...
}

Resources