I am writing a driver for an anemometer, which is based on the Hall effect and I am trying to use hardware interrupts to monitor every rotation of the sensor.
By doing so I found an issue that I am not able to solve and is expressed by the following code:
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
const int interruptPin = D5;
volatile uint16_t lastDebounceTime = 0;
volatile int numberOfInterrupts = 0;
uint16_t previousUpdate = 0;
const uint16_t updateInterval = 5000;
void handleInterrupt();
void countInterrupts();
void setup() {
Serial.begin(115200);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
}
void loop() {
if ((millis() - previousUpdate) > updateInterval) {
Serial.println(".................");
uint16_t currentMillis = millis();
Serial.println(currentMillis);
Serial.println(previousUpdate);
Serial.println(currentMillis - previousUpdate);
if (currentMillis - previousUpdate < updateInterval) Serial.println("This line shoudn't be executed, but it actually is!!");
Serial.println(".................");
previousUpdate = millis();
}
}
void handleInterrupt() {
numberOfInterrupts++;
}
At first the code run as it was supposed to, but after a while it simply stop checking the conditionals if ((millis() - previousUpdate) > updateInterval) and if (currentMillis - previousUpdate < updateInterval) Serial.println("This line shoudn't be executed, but it actually is!!"); and then the at each iteration the ESP8266 sends data to the serial interface. millis() is working the interrupt function is working as well.
I'm really trying to understand and solve this problem, it would be awesome if somebody could help me with it!
Thank you!
Related
I want to count milliseconds on my Pico to make nonblocking code in C++.
Arduino has the millis() function, but after looking though all the example programs and scouring the internet I couldn't find anything like that for the Pico using C++.
This is the BlinkWithoutDelay sketch from the Arduino examples that shows what I want to do:
const int ledPin = LED_BUILTIN;// the number of the LED pin
// Variables will change:
int ledState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change:
const 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, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// 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);
}
}
I decided to go with a repeating timer as suggested by some comments and the examples that used it really difficult to understand for me. So I'll try to explain it the best I can.
*Note that I don't really understand some of the values being passed into functions but I know enough to make this work. Please feel free to correct me
#include "pico/stdlib.h"
bool led_state;
//Function Called by the timer
bool timer_callback( repeating_timer_t *rt )
{
//Blinks the LED
led_state = !led_state;
gpio_put(25, led_state);
return (true);
}
int main(){
//From what I can tell this creates an identifier for the timer
static repeating_timer_t timer;
stdio_init_all();
//GPIO setting (GPIO_25 is the LED pin on the pico)
gpio_init(25);
gpio_set_dir(25, GPIO_OUT);
//Sets a repeating timer to call a function every 1000 milliseconds
//add_repeating_timer_ms( int interval_in_milliseconds, ?&function to call?, ???, ?timer identifier? );
add_repeating_timer_ms( 1000, &timer_callback, NULL, &timer );
while(true){
//Blinks LED briefly at a different interval than the repeating timer
//This is to show that my code isn't blocked
gpio_put(25, !led_state);
sleep_ms(50);
gpio_put(25, led_state);
sleep_ms(450);
}
return 0;
}
I have an ATTiny85 which I program using a sparkfun programmer (https://www.sparkfun.com/products/11801) and the ATTiny Board Manager I am using is: https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json
Below is my code, I am having trouble getting the interrupt to work when I ground Pin 2.
I have tested the LED does work outside of the interrupt (inside the loop). Any suggestions are welcome.
#include "Arduino.h"
#define interruptPin 2
const int led = 3;
bool lastState = 0;
void setup() {
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(interruptPin, pulseIsr, CHANGE);
pinMode(led, OUTPUT);
}
void loop() {
}
void pulseIsr() {
if (!lastState) {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
lastState = 1;
}
else {
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
lastState = 0;
}
}
I was way off.
Here is how to set up an interrupt on the ATTiny85 using the Arduino IDE (this example uses digital pin 4 (pin 3 on the chip):
#include "Arduino.h"
const byte interruptPin = 4;
const byte led = 3;
bool lastState = false;
ISR (PCINT0_vect) // this is the Interrupt Service Routine
{
if (!lastState) {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
lastState = true;
}
else {
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
lastState = false;
}
}
void setup() {
pinMode(interruptPin, INPUT_PULLUP); // set to input with an internal pullup resistor (HIGH when switch is open)
pinMode(led, OUTPUT);
// interrupts
PCMSK |= bit (PCINT4); // want pin D4 / pin 3
GIFR |= bit (PCIF); // clear any outstanding interrupts
GIMSK |= bit (PCIE); // enable pin change interrupts
}
void loop() {
}
I see one possible error with your Boolean data type. Boolean data types are either true or false. I see that your using it for variable lastState. The initialization to equal 0 is something that I don't think the compiler allows. Maybe you should try setting the bool variable to the following...
bool lastState = true;
if (!lastState) {
// what you want your code to perform if lastState is FALSE
}
else {
//what else you want your code to perform if lastState is TRUE
}
OR
bool lastState = true;
if (lastState) {
// what you want your code to perform if lastState is TRUE
}
else {
//what else you want your code to perform if lastState is FALSE
}
Here is a helpful pdf on Boolean data types, available for download through my Nextcloud instance.
https://nextcloud.point2this.com/index.php/s/so3C7CzzoX3nkzQ
I know this doesn't fully fix your problem, but hopefully this will help some.
I am executing a block of code every certain period of time. The time is indicated by the value of the potentiometer. Everything works well. But in some parts of the potentiometer it is as if the value were 0 or a very low number that makes the code block run continuously.
Here the piece of code:
const int p = A0;
unsigned long t = 0;
void start(){
Serial.begin(9600);
}
void loop(){
if(millis() > t+(analogRead(p)*100)){
t = millis();
Serial.println("Something...");
}
}
Your start() function is wrong, it should be setup() and should include pin mode declaration.
void setup(){
Serial.begin(9600);
pinMode(p, INPUT);
}
I am try to do a write to serial using a NANO. This is my current code
#include "HardwareSerial.h"
long previousMillis = 0;
long interval = 2000;
void setup() {
// put your setup code here, to run once:
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
HardwareSerial serial = Serial;
serial.write("hello");
}
}
However when I monitor the serial using a serial monitor I only get
he
for each serial write. Please help
I have changed the class type in my method from hardwareserial to stream &serial this is now working the way it should. Thanks for the help
I am trying to make the LED flash on my arduino without using any function other than millis() within setup() and loop(). Here is what I have so far:
long previousMillis = 0;
long interval = 1000;
void setup()
{
DDRB = DDRB | B11111100;
}
void loop()
{
if ((unsigned long)(millis() - previousMillis) >= interval)
{
if ( PORTB == B00000000)
PORTB = B00100000;
else
PORTB = B00000000;
}
}
All it does is make the light go on and stay on though. I would appreciate any help! Thank you!
You aren't resetting previousMillis at all so once (millis() - previousMillis) >= interval is true, it will stay true forever.
What this means is your light will be flashing on and off so fast, it will appear as though its permanently on.
Add: previousMillis = millis() to the end of your loop() function.