arduino interrupt variable not working - arduino

I am a beginner with arduino and I'm trying to make a sinus wave generator. Since I've recently found I can't put everything into main void loop, I'm trying to use interrupts. I have problem with changing variable inside of the interrupt (Delay), I don't know where's the mistake.
Here is my code:
int sine256[] = { //256 sin values from 0 to 2pi
};
int i = 0;
int sensorPin = 7;
int outputPin = 6;
volatile float Delay = 10000;
void setup()
{
Serial.begin(9600);
pinMode(outputPin, OUTPUT);
pinMode(sensorPin, INPUT);
attachInterrupt(digitalPinToInterrupt(sensorPin), freq, RISING);
}
void loop()
{
analogWrite(6,sine256[i]);
i = i + 1;
if(i == 256){
i = 0;
}
Serial.println(Delay);
delayMicroseconds(Delay);
}
void freq() {
Delay = Delay/2;
}

EDIT
Try this:
int sine256[] = { //256 sin values from 0 to 2pi
};
int i = 0;
int sensorPin = 7;
int outputPin = 6;
volatile float Delay = 10000;
void setup()
{
Serial.begin(9600);
pinMode(outputPin, OUTPUT);
pinMode(sensorPin, INPUT);
//attachInterrupt(digitalPinToInterrupt(sensorPin), freq, RISING);
}
void loop()
{
analogWrite(6,sine256[i]);
i = i + 1;
if(i == 256){
i = 0;
}
Serial.println(Delay);
freq();
delay(Delay);
}
void freq() {
Delay = Delay / 2;
}
https://www.arduino.cc/en/Reference/AttachInterrupt
Try taking a look at that.
What model are you using?

The only thing that causes me troubles now is the button; when i press it, it often respond as if i had pressed the button multiple times (2,3 or 4x).
This is my final code for now. Since the execution time for a void loop is 12 microseconds, i've calculated delay required to run a generator on 20,40 & 60Hz.
int sine256[] = { //256 sin values from 0 to 2pi (from 0 to 255)
int i = 0;
int sensorPin = 2;
volatile int outputPin = 7;
volatile float Delay = 1000;
int time1;
int time2;
void setup()
{
Serial.begin(9600);
pinMode(outputPin, OUTPUT);
pinMode(sensorPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(sensorPin), freq, FALLING);
}
void loop()
{
//time1 = micros();
analogWrite(outputPin,sine256[i]);
i = i + 1;
if(i == 256){
i = 0;
}
//time2 = micros();
//Serial.println(time2 - time1);
delay(Delay);
}
void freq() {
outputPin = 6;
if(Delay == 0.02){
analogWrite(6,LOW);
outputPin = 7;
Delay = 1000;
}
if(Delay == 0.04){
Delay = 0.02;
}
if(Delay == 0.09){
Delay = 0.04;
}
if((Delay == 1000)&&(outputPin == 6)){
Delay = 0.09;
}
Serial.println(Delay);
}

Related

Question on Two servo project activated by timer and water level sensor

I am using a arduino uno in an attempt to power two servos. Servo A should open for a couple seconds every 24 hours OR if button A is pressed. Servo B should open for a couple seconds if the water level sensor reads below 300 OR if button B is pressed. The code below works fine when I only include one servo, but adding the code for servo B ruins everything.
#include <Servo.h>
Servo myservoA;
Servo myservoB;
const int BUTTONA_PIN = 8;
const int BUTTONB_PIN = 6;
const int SERVOA_PIN = 9;
const int SERVOB_PIN = 7;
unsigned long dayTimer_ms = 0;
unsigned long autoOpenDelay_ms = 86400000;
int angle = 0;
int waterSensor = A0;
int waterLevel = 0;
void setup(){
myservoA.attach(SERVOA_PIN);
myservoB.attach(SERVOB_PIN);
pinMode(BUTTONA_PIN, INPUT_PULLUP);
pinMode(BUTTONB_PIN, INPUT_PULLUP);
myservoA.write(0);
myservoB.write(0);
}
void loop() {
if(millis() - dayTimer_ms > autoOpenDelay_ms)
{
dayTimer_ms = millis();
myservoA.write(180); //(open?)
delay(8000);
myservoA.write(0);
}
if(millis()<dayTimer_ms)//overflow handling (in case this runs for more than 50 days straight)
{
dayTimer_ms = millis();
}
if (!digitalRead(BUTTONA_PIN) && angle != 180)
{
angle = 180;
myservoA.write(angle);
}
if (digitalRead(BUTTONA_PIN) && angle != 0)
{
angle = 0;
myservoA.write(angle);
}
if (!digitalRead(BUTTONB_PIN) && angle != 180)
{
angle = 180;
myservoB.write(angle);
}
if (digitalRead(BUTTONB_PIN) && angle != 0)
{
angle = 0;
myservoB.write(angle);
}
int waterLevel = analogRead(waterSensor);
if (waterLevel <= 300){
myservoB.write(180);
delay(8000);
myservoB.write(0);
}
}
You are actually super close!
You just need to make a second variable to track angleA separately from angleB. So you should initialize another variable at the top "angleB" to zero and then replace "angle" with this new variable everywhere below line 52
#include <Servo.h>
Servo myservoA;
Servo myservoB;
const int BUTTONA_PIN = 8;
const int BUTTONB_PIN = 6;
const int SERVOA_PIN = 9;
const int SERVOB_PIN = 7;
unsigned long dayTimer_ms = 0;
unsigned long autoOpenDelay_ms = 86400000;
int angleA = 0;
int angleB = 0;
int waterSensor = A0;
int waterLevel = 0;
void setup(){
myservoA.attach(SERVOA_PIN);
myservoB.attach(SERVOB_PIN);
pinMode(BUTTONA_PIN, INPUT_PULLUP);
pinMode(BUTTONB_PIN, INPUT_PULLUP);
myservoA.write(0);
myservoB.write(0);
}
void loop() {
if(millis() - dayTimer_ms > autoOpenDelay_ms)
{
dayTimer_ms = millis();
myservoA.write(180); //(open?)
delay(8000);
myservoA.write(0);
angleA = 0;
}
if(millis()<dayTimer_ms)//overflow handling (in case this runs for more than 50 days straight)
{
dayTimer_ms = millis();
}
if (!digitalRead(BUTTONA_PIN) && angleA != 180)
{
angleA = 180;
myservoA.write(angleA);
}
if (digitalRead(BUTTONA_PIN) && angleA != 0)
{
angleA = 0;
myservoA.write(angleA);
}
if (!digitalRead(BUTTONB_PIN) && angleB != 180)
{
angleB = 180;
myservoB.write(angleB);
}
if (digitalRead(BUTTONB_PIN) && angleB != 0)
{
angleB = 0;
myservoB.write(angleB);
}
int waterLevel = analogRead(waterSensor);
if (waterLevel > 300 && angleB != 0)
{
myservoB.write(0);
angleB = 0;
}
else if (waterLevel < 200 && angleB != 180){
myservoB.write(180);
angleB = 180;
}
}
the bottom two levels may need to be adjusted (200 and 300). Basically this creates a slight de-bounce. By separating the levels at which the water turns on and turns off, it keeps the system from jittering right at the limit (constantly turning on and off). That being said, depending on the accuracy of your sensor and how important precise level control is in your application, you may want to tighten or move these values around a bit.

Attachinterrupt frequency arduino

I have this project where i need to build a synthethiser , our only problem is getting the frequency back to arduino. I don't have a picture of it but heres a simulation on proteus.
enter image description here
I tried to calculate the period for 500ms and then divide it by each rising that occured but i only get 0 for my frequency
volatile int prev_time = 0;
volatile int now_time = 0;
volatile int periode1 = 0;
volatile int periode = 0;
volatile int frequence = 0;
volatile int compteur=0;
unsigned long tempsactuel=millis();
int donnee = 2;
void setup()
{
Serial.begin(115200);
pinMode(donnee, OUTPUT);
attachInterrupt(digitalPinToInterrupt(donnee), rising, RISING);
}
void loop()
{
if(tempsactuel>500)
{
periode=periode/compteur;
frequence=1/periode;
compteur=0;
periode=0;
tempsactuel=0;
}
Serial.println(periode);
Serial.println(frequence);
}
void rising()
{
now_time = micros();
periode1 = now_time - prev_time;
prev_time = now_time;
periode=periode1+periode;
compteur++;
}
(Btw I can't use timer1 since i'm already using it for something else)
volatile int prev_time = 0;
volatile int now_time = 0;
volatile int periode1 = 0;
volatile int periode = 0;
float frequence = 0;
volatile int compteur=0;
unsigned long tempsactuel=millis();
unsigned long tempsprecedent=0;
int donnee = 2;
void setup()
{
Serial.begin(115200);
pinMode(donnee, OUTPUT);
attachInterrupt(digitalPinToInterrupt(donnee), rising, RISING);
}
void loop()
{
if(tempsactuel-tempsprecedent>500)
{
periode=periode/compteur;
frequence=1/(float)periode;
compteur=0;
periode=0;
tempsprecendent=tempsactuel;
}
Serial.println(periode);
Serial.println(frequence);
}
void rising()
{
now_time = micros();
periode1 = now_time - prev_time;
prev_time = now_time;
periode=periode1+periode;
compteur++;
}

How can I get out of the loop?

I'd like to get out of the loop in my Arduino project. Currently I am programming a digital watch, everything works just fine but I wanted to add options menu by clicking a button, but after clicking it nothing pops up even if I have something inside the code. Take a look at it. I don't know how to write it better. If you have some ideas, please you could rewrite some parts of the code and explain why you did so. Thanks forwardly.
Please do not mind s = s + 1, I wanted it like that.
#include "LiquidCrystal.h"
#include <EEPROM.h>
LiquidCrystal lcd(12,11,5,4,3,2);
int h = 0;
int m = 0;
int s = 0;
int right = 8;
int left = 9;
int buttonStateLeft = 0;
String when;
uint8_t EEPROMaddress_sec = 1;
uint8_t EEPROMaddress_min = 2;
uint8_t EEPROMaddress_hour = 3;
bool clockShown = true;
bool menuShown = false;
void setup()
{
lcd.begin(16,2);
pinMode(right, INPUT);
pinMode(left, INPUT);
}
void loop()
{
if(menuShown)
{
lcd.setCursor(0,0);
lcd.print("jozo je kkt");
delay(200);
}
if(clockShown) {
lcd.setCursor(0,0);
buttonStateLeft = digitalRead(left);
if(buttonStateLeft == HIGH)
{
clockShown = false;
menuShown = true;
lcd.clear();
}
s = EEPROM.read(EEPROMaddress_sec);
m = EEPROM.read(EEPROMaddress_min);
h = EEPROM.read(EEPROMaddress_hour);
s = s + 1;
if(h > 12)
when = "PM";
if(h < 12)
when = "AM";
if(h == 12)
when = "PM";
lcd.print("Cas: ");
if(h<10)lcd.print("0");
lcd.print(h);
lcd.print(":");
if(m<10)lcd.print("0");
lcd.print(m);
lcd.print(":");
if(s<10)lcd.print("0");
lcd.print(s);
lcd.print(" ");
lcd.print(when);
if(s == 60)
{
s = 0;
m = m+1;
}
if(m == 60)
{
s = 0;
m = 0;
h = h+1;
}
if(h == 24)
{
m = 0;
s = 0;
h = 0;
}
EEPROM.write(EEPROMaddress_sec, s);
EEPROM.write(EEPROMaddress_min, m);
EEPROM.write(EEPROMaddress_hour, h);
delay(1000);
}
}
In order to do that you will have to use Interrupts, note that you must connect your button to an interrupt pin (not every pin is an interrupt pin) you can google "what are the interrupt pins of 'your_card_name' ", the code would have to change, you can follow these :
In the setup function replace :
pinMode(left, INPUT);
by :
attachInterrupt(digitalPinToInterrupt(left), switchMode, RISING);
add this function before setup(){...}
int lastPressTime=millis();
void switchMode(){ // function called when the button is pressed
if((millis()-lastPressTime)>60){ // for debouncing
clockShown = false;
menuShown = true;
lcd.clear();
lastPressTime=millis();
}
}
and remove this part from your code : (the one in the loop() function)
buttonStateLeft = digitalRead(left);
if(buttonStateLeft == HIGH)
{
clockShown = false;
menuShown = true;
lcd.clear();
}

Arduino hardware interrupt reliability issue

This may seem like a foolish problem and maybe its description is not the best I could have devised.
I am making a velocity sensor that uses two IR beams to calculate velocity based on the time it takes to break both beams.
I have two testing methods.
My hand (5-10 m/s)
A high speed cannon (30-60 m/s).
I have ruled out that it's a problem with the signal from the IR beams with an oscilloscope, when the code fails/works the data is identical on the scope.
My problem is that my code works when I use my hand, but still irregularly fails, while it fails more often at high speed. All the conditions are the same in both scenarios. What could be the issue?
#include <SPI.h>
#include <SD.h>
#include <LiquidCrystal.h>
const int rs = 9, en = 8, d4 = 7, d5 = 6, d6 = 5, d7 = 4;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
File root;
int fileNo = 0;
String currentFileName;
const int CS = 10;
const byte interruptPinStart = 2;
const byte interruptPinFinish = 3;
volatile unsigned long int startTimeMillis = 0;
volatile unsigned long int stopTimeMillis = 0;
volatile unsigned long int startTimeMicros = 0;
volatile unsigned long int stopTimeMicros = 0;
volatile unsigned long int microsDifference = 0;
volatile unsigned long int millisDifference = 0;
int launchNo = 0;
float currentVelocity = 0;
volatile boolean started = false;
String inputString = "";
boolean stringComplete = false;
const int txLed1 = 14;
const int statusLed1 = 15;
const int statusLed2 = 16;
volatile boolean triggerDone = false;
float velocity = 0;
String temp;
unsigned long int lockout = 0;
boolean lockedOut = false;
boolean fileFail = false;
int testNo = 0;
void setup() {
inputString.reserve(200);
pinMode(statusLed1, OUTPUT);
pinMode(statusLed2, OUTPUT);
pinMode(txLed1, OUTPUT);
Serial.begin(9600);
while (!Serial) {
;
}
lcd.begin(16, 2);
pinMode(interruptPinStart, INPUT);
attachInterrupt(digitalPinToInterrupt(interruptPinStart), startTrigger, RISING);
pinMode(interruptPinFinish, INPUT);
attachInterrupt(digitalPinToInterrupt(interruptPinFinish), stopTrigger, RISING);
Serial.print("Initializing SD card...");
if (!SD.begin(CS)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
root = SD.open("/");
newDirectory(root);
Serial.println("done!");
lcd.clear();
lcd.print(currentFileName);
tone(txLed1, 38000);
}
void loop() {
int millsDiff = millis() - stopTimeMillis;
if (triggerDone) {
lockedOut = true;
Serial.print("Micros Diffrence: ");
Serial.println(microsDifference);
Serial.print("Millis Difference: ");
Serial.println(millisDifference);
float millDiff = (float) millisDifference;
float microDiff = (float) microsDifference;
if (microDiff > 0) {
velocity = (float) 0.09 / (microDiff/1000000);
testNo++;
temp = String(launchNo) + "%" + String(microsDifference) + "%" + String(velocity);
if (velocity > 10.0) {
root = SD.open(currentFileName, FILE_WRITE);
if (root) {
root.println(temp);
root.close();
Serial.println(temp);
launchNo++;
} else {
Serial.println("error opening file, " + currentFileName);
fileFail = true;
}
}
if (fileFail) {
lcd.clear();
lcd.print("File Error");
lcd.setCursor(0, 1);
lcd.print("Vel " + String(launchNo) + ": " + String(velocity) + " m/s");
fileFail = false;
} else {
lcd.clear();
lcd.print("Test Number: " + String(testNo));
lcd.setCursor(0, 1);
lcd.print("Vel " + String(launchNo) + ": " + String(velocity) + " m/s");
}
}
triggerDone = false;
Serial.println("Test Number: " + String(testNo));
}
if (digitalRead(interruptPinStart) == LOW) {
digitalWrite(statusLed1, HIGH);
} else {
digitalWrite(statusLed1, LOW);
}
if (digitalRead(interruptPinFinish) == LOW) {
digitalWrite(statusLed2, HIGH);
} else {
digitalWrite(statusLed2, LOW);
}
}
void startTrigger() {
startTimeMicros = micros();
startTimeMillis = millis();
volatile int diff1 = startTimeMicros - startTimeMillis;
volatile int diff2 = startTimeMillis - stopTimeMillis;
if (diff2 > 200) {
if (started == false || diff1 > 1000) {
started = true;
triggerDone = false;
}
}
}
void stopTrigger() {
stopTimeMicros = micros();
stopTimeMillis = millis();
microsDifference = stopTimeMicros - startTimeMicros;
millisDifference = stopTimeMillis - startTimeMillis;
if ((millisDifference > 0 && millisDifference < 800) && started) {
microsDifference = stopTimeMicros - startTimeMicros;
millisDifference = stopTimeMillis - startTimeMillis;
started = false;
triggerDone = true;
}
}

Storing the value read previously until new pulse

I'm currently doing a project on an Arduino Uno. The project is based on receiving an IR Signal from an IR Remote and then based on the signal received, perform other operations.
The problem is that the signal gets reset every time. I want to store the value received from the IR Remote and then resets it if detects another pulse.
Here is my code :
int brojac = 0;
int pinData = 10;
unsigned long lengthHeader;
unsigned long bit;
int byteValue;
int vrime = 1000 ;
int storeValue = 0;
void setup()
{
Serial.begin(9600);
pinMode(pinData, INPUT);
}
void loop() {
lengthHeader = pulseIn(pinData, LOW);
if (lengthHeader > 1500)
{
for (int i = 1; i <= 32; i++) {
bit = pulseIn(pinData, HIGH);
if (i > 16 && i <= 24)
if (bit > 1000)
byteValue = byteValue + (1 << (i - 17));
}
}
Serial.print("byteValue = ");
Serial.println(byteValue);
if(byteValue == 66){
digitalWrite(11,HIGH);
}
else{
digitalWrite(11,LOW);
}
delay(vrime);
byteValue = 0;
delay(250);
}
I got the answer by storing the value in a variable until a new variable is detected.
int pinData = 10;
int led = 11;
unsigned long lengthHeader;
unsigned long bit;
int byteValue;
int storeValue = 0;
int previousValue = 0;
void setup()
{
Serial.begin(9600);
pinMode(pinData, INPUT);
pinMode(led, LOW);
}
void loop() {
lengthHeader = pulseIn(pinData, LOW);
if (lengthHeader > 1500)
{
for (int i = 1; i <= 32; i++) {
bit = pulseIn(pinData, HIGH);
if (i > 16 && i <= 24)
if (bit > 1000)
byteValue = byteValue + (1 << (i - 17));
}
}
Serial.print("byteValue = ");
Serial.println(byteValue);
**storeValue = byteValue;
if (storeValue != 0){
previousValue = storeValue;
}
Serial.print("Previous value = ");
Serial.println(previousValue);**
byteValue = 0;
delay(500);
}

Resources