Toggle pin on Arduino Micro without disrupting operation - arduino

I have a code that once it receives a particular input over the serial it will turn 2 pins high, and wait for an interrupt to occur and run its code. I tried using an infinite loop(while 1) but the interrupt routine can't get executed when the button is pressed.
I want the outputs LED and BEEP to toggle after 'C' is received and until the interrupt occurs.
// Declarations before
void loop() {
while(Serial.available())
{
char data = Serial.read();
if(data == 'C')
{
digitalWrite(BEEP, 1);
digitalWrite(LED, 1);
flag = true;
}
}
// Interrupt routine

When this code receives a 'C' char from the serial the code starts a led flashing for 50 msec on and for 50 msec off, the led flashing stops when the interrupt ITR_PIN is generated (the ISR buttonPressed function will be called!)
#define ITR_PIN 3
volatile bool start = false;
bool ledstatus = false;
int LED= 4;
/**
* This method is called on the interruption raised on the falling front of the PIN2
* The start flag is used to avoid rebound front. Interruptions are disabled inside the
* interrupt vector method.
* start is reset once it has been processed in the main loop()
*/
void buttonPressed()
{
start=false;
}
void setup()
{
cli();
pinMode(ITR_PIN, INPUT);
pinMode(LED, OUTPUT);
attachInterrupt(0, buttonPressed, FALLING); // Pin 3
sei();
Serial.begin(9600);
}
void loop(){
while(Serial.available())
{
char data = Serial.read();
if(data == 'C')
{
start = true;
}
}
if (start)
{
ledstatus=!ledstatus;
digitalWrite(LED, (ledstatus)?HIGH:LOW);
delay(50);
} else {
if (ledstatus) {
ledstatus=false;
digitalWrite(LED,LOW);
}
}
}

I just tried this on a simulator:
#define ITR_PIN 3
volatile boolean start = false;
volatile boolean flag = false;
int LED= 4;
/**
* This method is called on the interruption raised on the falling front of the PIN2
* The start flag is used to avoid rebound front. Interruptions are disabled inside the
* interrupt vector method.
* start is reset once it has been processed in the main loop()
*/
void buttonPressed()
{
if(flag)
{
if (!start)
{
start = true;
}
}
}
void setup()
{
cli();
pinMode(ITR_PIN, INPUT);
pinMode(LED, OUTPUT);
attachInterrupt(0, buttonPressed, FALLING); // Pin 3
sei();
Serial.begin(9600);
}
void loop(){
while(Serial.available())
{
char data = Serial.read();
if(data == 'C')
{
digitalWrite(LED, 1);
flag = true;
}
}
if(flag == true)
if (start)
{
digitalWrite(LED, LOW);
delay(50);
start = false;
flag=false;
}
}
(it's just a reduced version of yours, I just removed the stepper dependancies and marked flag as volatile). It works with this hardware:
However, I'm pretty sure that you haven't added the pullup to your circuit!
The solution is:
add a resistor (e.g. 10 kOhm) between pin 3 and +5V
enable the internal pullup
Solution 2 is the preferred one: you just have to change
pinMode(ITR_PIN, INPUT);
into
pinMode(ITR_PIN, INPUT_PULLUP);
EDIT:
According to your comment I think that the behavior should be different:
Everything is off
When you receive a C on the serial interface the led starts "blinking"
When the interrupt is asserted it stops blinking.
I modified the code to achieve this; I slightly reduced the rest of the code (but you can merge it with the previous one)
#define ITR_PIN 3
volatile boolean flag = false;
const int blink_period_ms = 500; // Blink period in milliseconds
unsigned long initialBlinkTime;
int LED= 4;
void buttonPressed()
{
flag = false;
}
void setup()
{
cli();
pinMode(ITR_PIN, INPUT);
pinMode(LED, OUTPUT);
attachInterrupt(0, buttonPressed, FALLING); // Pin 3
sei();
Serial.begin(9600);
}
void loop(){
while(Serial.available())
{
char data = Serial.read();
if(data == 'C')
{
if (!flag)
{
initialBlinkTime = millis();
flag = true;
}
}
}
if(flag)
{
int currentTime = millis() - initialBlinkTime;
while (currentTime > blink_period_ms) currentTime -= blink_period_ms;
digitalWrite(LED, currentTime < blink_period_ms/2);
// Insert here the other instructions
delay(50);
}
}

Related

Master - Slave using SPI communication (Tinkercad)

Need your help again: I'm doing this time Master - Slave Using SPI communication, there is no error in the code when I simulate the code but the LED won't turn on.
The supposed outcome that should happen is that when I push the push button on master board the LED on the slave board will turn on.
Master code:
// Master Board
#include <SPI.h>
#define button1 4
#define SS 10
int buttonvalue;
int x;
void setup(void) {
Serial.begin(115200); //set baud rate to 115200 for usart
digitalWrite(SS, HIGH); // disable Slave Select
SPI.begin ();
SPI.setClockDivider(SPI_CLOCK_DIV8); //divide the clock by 8
}
void loop(void) {
digitalWrite(SS, LOW);
buttonvalue = digitalRead(button1);
if (buttonvalue == HIGH) {
x = 1;
} else {
x = 0;
}
digitalWrite(SS, HIGH);
delay(1000);
}
Slave code:
// Slave Board
#include <SPI.h>
#define led1 2
volatile byte Slavereceived;
volatile boolean received;
int x;
void setup(void) {
Serial.begin(115200);
pinMode(2, OUTPUT);
pinMode(MISO,OUTPUT);
SPCR |= _BV(SPE);
received = false;
SPI.attachInterrupt();
}
ISR (SPI_STC_vect) {
Slavereceived = SPDR;
received = true;
}
void loop() {
if (received) {
if (Slavereceived == 1) {
digitalWrite(led1, HIGH);
} else {
digitalWrite(led1, LOW);
}
delay(1000);
}
}
I too was stuck in the same situation, there is no support for the SPI library in tinkercad, you can include it without errors, and even use it, but any useful command will let the code stuck at that command
Sorry, but there no much you can do
this link if for a tinkercad forum, where one of the people said SPI library amoung two others are not supported
Add SPI.transfer(x); below the if else to your master code.
The master code will look somewhat like this:
// Master Board
#include <SPI.h>
#define button1 4
#define SS 10
int buttonvalue;
int x;
void setup(void) {
Serial.begin(115200); //set baud rate to 115200 for usart
digitalWrite(SS, HIGH); // disable Slave Select
SPI.begin ();
SPI.setClockDivider(SPI_CLOCK_DIV8); //divide the clock by 8
}
void loop(void) {
digitalWrite(SS, LOW);
buttonvalue = digitalRead(button1);
if (buttonvalue == HIGH) {
x = 1;
} else {
x = 0;
}
SPI.transfer(x);
digitalWrite(SS, HIGH);
delay(1000);
}

Implementing the function interrupt with if statements

I want to implement the function interrupt () but I don't know exactly how..In this case there is 2 for loops which can be seen in the code:I want whenever one of the 2 buttons is pressed the process inside the loop to be interrupted immediately:
void loop() {
int brightButton = digitalRead(K1);
int ldrStatus = analogRead(ldrPin);
if (brightButton == LOW && ldrStatus >= 200)
{
for (int i = 0; i < 10; i++)
{
digitalWrite(greenLed, HIGH);
tone(buzzer,400);
delay(500);
noTone(buzzer);
delay(500);
}
}
else {
digitalWrite(greenLed, LOW);
}
int tempButton = digitalRead(K2);
int valNTC = analogRead(NTC);
if (tempButton == LOW && valNTC > 512)
{
for (int i = 0; i <10; i++)
{
digitalWrite(redLed, HIGH);
tone(buzzer,450);
delay(300);
noTone(buzzer);
delay(1000);
}
}
else {
digitalWrite(redLed, LOW);
}
}
Example code from the Arduino manual:
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}
void loop() {
digitalWrite(ledPin, state);
}
void blink() {
state = !state;
}
Note that this will interrupt the for loop and return to it once the interrupt service routine is finished.
If you want to abort the for loop check the pin state in every loop cycle and break if you want to leave the for loop or return if you want to leave loop().
Of course this is not "immediately".

Problem with interruptions in Arduino Uno

I work with interruptions in Arduino UNO. In this project, I want to when the Door is opened the LED blink 10 times, and when the door is closed again, stop blinking the LED and exit the function. But in this code the LED only turn on and off once and it does not flash again.
My other problem is that, when the door is opened or closed, sometimes the opened or closed word appears several times in the Series monitor.
const byte LED_Red = 13;
const byte DOOR_SENSOR = 2; // magnetic door sensor pin
volatile int SensorState = LOW; // 0 close - 1 open wwitch
void setup()
{
Serial.begin(9600);
pinMode(LED_Red, OUTPUT);
pinMode(DOOR_SENSOR, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(DOOR_SENSOR), DoAction, CHANGE);
}
void DoAction()
{
SensorState = digitalRead(DOOR_SENSOR);
if (SensorState == HIGH) {
Serial.println("Opened");
blinkLED(10, 500);
}
else {
Serial.println("Closed");
}
}
void blinkLED(int repeats, int time)
{
for (int i = 0; i < repeats; i++) {
if (SensorState == HIGH) {
digitalWrite(LED_Red, HIGH);
delay(time);
digitalWrite(LED_Red, LOW);
delay(time);
}
else
return;
}
}
void loop()
{
}
You can't simply put a delay() on an interrupt's function. You need to just set a flag when the door is opened and based on that start blinkLED inside the main loop.
I also recommend you to use millis() function for an unblocking delay inside blinkLED function (e.g when you want to stop blinking while the door is closed).
const byte LED_Red = 13;
const byte DOOR_SENSOR = 2; // magnetic door sensor pin
// flag to check door is opened
volatile bool isOpened = false;
//flag to check already blinked
volatile bool isBlinked = false;
void setup()
{
Serial.begin(9600);
pinMode(LED_Red, OUTPUT);
pinMode(DOOR_SENSOR, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(DOOR_SENSOR), DoAction, CHANGE);
}
void DoAction()
{
if (digitalRead(DOOR_SENSOR) == HIGH)
{
//Serial.println("Opened");
isOpened = true;
}
else
{
isOpened = false;
isBlinked = false;
//Serial.println("Closed");
}
}
void blinkLED(int repeats, int time)
{
byte LEDState = LOW;
unsigned long delay_start = millis();
for (int i = 0; i < 2 * repeats; i++)
{
//Toggle LED state
if (LEDState == HIGH)
LEDState = LOW;
else
LEDState = HIGH;
// set value
digitalWrite(LED_Red, LEDState);
// some unblocking delay
while (millis() - delay_start < time)
{
// return if door is closed
if (!isOpened)
{
// turn off LED
digitalWrite(LED_Red, LOW);
return;
}
}
delay_start = millis();
}
isBlinked = true;
}
void loop()
{
// Check isBlinked beacue don't want to blink again until door is closed
if (isOpened && !isBlinked)
{
blinkLED(10, 500);
}
}

PIC16F628A to Arduino RF Communication Fails (433MHz)

I have pic16f628a and Arduino UNO...
I use MikroC for PIC...
I use 433 mhz transmitter and receiver.
My purpose is reading datas from Arduino UNO which I send from PIC16F628A; but I couldn't success it...
The circuit of PIC16F628A (Transmitter):
The circuit of Transmitter
I connected first pin of receiver to +5V of Arduino;
second pin of receiver to 12.pin of Arduino,
last pin of receiver to GND pin of Arduino.
Transmitter(PIC16F628A):
char pre[15]={'U','U','U','U','U',255,255,255,255,255,0,0,0,0,0}; //start bytes...
char ileri[3]={'f','r','w'};
char geri[3]={'b','c','k'};
char dur[3]={'d', 'u', 'r'};
char i=0,j=0;
void kurulum()
{
CMCON= 7;
TRISB= 2;
UART1_Init(2400);
delay_ms(100);
}
void main()
{
kurulum();
while(1)
{
for(i=0;i<15;i++)
{
UART1_Write(pre[i]);
}
for(j=0;j<10;j++)
{
for(i=0;i<3;i++)
{
while(!UART1_Tx_Idle());
UART1_Write(ileri[i]);
}
}
//*************************************************************
for(i=0;i<15;i++)
{
UART1_Write(pre[i]);
}
for(j=0;j<10;j++)
{
for(i=0;i<3;i++)
{
while(!UART1_Tx_Idle());
UART1_Write(geri[i]);
}
}
for(i=0;i<15;i++)
{
UART1_Write(pre[i]);
}
for(j=0;j<10;j++)
{
for(i=0;i<3;i++)
{
while(!UART1_Tx_Idle());
UART1_Write(dur[i]);
}
}
}
}
Receiver (Arduino):
// receiver.pde
//
// Simple example of how to use VirtualWire to receive messages
// Implements a simplex (one-way) receiver with an Rx-B1 module
//
// See VirtualWire.h for detailed API docs
// Author: Mike McCauley (mikem#airspayce.com)
// Copyright (C) 2008 Mike McCauley
// $Id: receiver.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $
#include <VirtualWire.h>
const int led_pin = 13;
const int receive_pin = 12;
void setup()
{
delay(1000);
Serial.begin(9600); // Debugging only
Serial.println("setup");
// Initialise the IO and ISR
vw_set_rx_pin(receive_pin);
//vw_set_ptt_inverted(true); // Required for DR3100
vw_setup(2400); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
pinMode(led_pin, OUTPUT);
}
void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Non-blocking
{
int i;
digitalWrite(led_pin, HIGH); // Flash a light to show received good message
// Message with a good checksum received, dump it.
Serial.print("Got: ");
for (i = 0; i < buflen; i++)
{
Serial.print(buf[i], HEX);
Serial.print(' ');
}
Serial.println();
digitalWrite(led_pin, LOW);
}
}
I tried this code; but it didn't work...
There is another code;
void setup() {
Serial.begin(2400);
}
void loop() {
if (Serial.available() > 0){
Serial.println(Serial.read());
}
}
Before trying it; I connected data pin of receiver to RX pin of Arduino...
I usually got '0' byte.i
It didn't work as I desired...
SOLVED
The tests I have done so far were already taking the true datas but I was viewing them as numbers...
That's why I couldn't understand that It was working well.
Let's have a look at codes;
Transmitter:
The same as transmitter code at question message
Arduino (Receiver):
char x, msg[6];
int i= 0;
void setup() {
Serial.begin(2400);
}
void loop() {
if (Serial.available() > 0){
msg[i] = Serial.read();
if (msg[0]=='f' || msg[0] == 'b' || msg[0] == 'd'){
i++;
}
if (i==3){
Serial.println(msg);
i = 0;
msg[0]=0;
}
}
}
msg[0]=='f' || msg[0] == 'b' || msg[0] == 'd'
The purpose of comparison above is catching "frw", "bck" or "dur" messages which I sent transmitter...
The data pin of the receiver should be connected RX pin of the Arduino...

Arduino program that allows me to change state through comm port?

new here! been recommended many times to come here for help so here I am.
I'm supposed to write a program that allows me to change the rate of a blinking LED light through the comm port. I'm sure this is easy but I've honestly got no clue as I am behind in this class.
anything would help really, i honestly want to learn how to do this, not just come here and get the answer.
thanks in advanced!
// global variables
#include <EEPROM.h>
unsigned long ms_runtime;
int state;
// possible values 0 -> 1 -> 2 -> 3 -> 0
int one_ms_timer;
// define all timers as unsigned long (they are incremented every 100ms = 0.1s)
unsigned long timer1;
unsigned long button_dbnc_tmr = 0;
// timer1 is used for blinking LED
const int LED1 = 13;
// function prototypes
void read_memory(void);
void update_memory(void);
void comm_control(void);
void led_control(void);
void turnoff(void);
void flash_1s(void);
void flash_2s(void);
void flash_3s(void);
void timers(void);
void setup()
{
read_memory();
pinMode(LED1, OUTPUT);
Serial.begin(9600);
//initialize uart
}
void loop()
{
static bool allow_change;
static int counter;
timers();
comm_control();
led_control();
}
void led_control()
{
switch (state)
{
case 0:
turnoff();
break;
case 1:
flash_1s();
break;
case 2:
flash_2s();
break;
case 3:
flash_3s();
break;
}
}
void turnoff()
{
digitalWrite(LED1, LOW);
}
void flash_1s()
{
if (timer1 < 10)
digitalWrite(LED1, HIGH);
else
{
digitalWrite(LED1, LOW);
if (timer1 >= 20)
timer1 = 0;
}
}
void flash_2s()
{
if (timer1<20)
digitalWrite(LED1, HIGH);
else
{
digitalWrite(LED1, LOW);
if (timer1 >= 30)
timer1 = 0;
}
}
void flash_3s()
{
if (timer1<30)
digitalWrite(LED1, HIGH);
else
{
digitalWrite(LED1, LOW);
if (timer1 >= 40)
timer1 = 0;
}
}
void read_memory()
{
timer1 = EEPROM.read(one_ms_timer);
timer1++;
EEPROM.write(one_ms_timer, timer1);
Serial.begin(9600);
}
void update_memory()
{
EEPROM.update(timer1, one_ms_timer);
}
void comm_control(void);
{
char comm_reveier = serial_read;
if (
)
}
void timers(void)
{
if (millis() > (ms_runtime + 1))
{
ms_runtime = ms_runtime + 1;
one_ms_timer++;
}
else if (ms_runtime > millis())
ms_runtime = millis();
if (one_ms_timer > 99) //every 100 ms
{
one_ms_timer = 0;
button_dbnc_tmr++;
timer1++;
}
}
Load the Standard Firmata library on your Arduino board. Then use a library of your choice to build your comm prog. An overview of these can be found here.
Assuming you are using the Arduino IDE, this code sample should give you the general idea of what you need to do:
// pins for the LEDs:
const int ledPin = 13;
// Default blink rate
int rate = 1000;
void setup() {
// initialize serial:
Serial.begin(9600);
// make the pins outputs:
pinMode(ledPin, OUTPUT);
}
void loop() {
// if there's any serial available, read it:
while (Serial.available() > 0) {
// look for the next valid integer in the incoming serial stream:
int rate = Serial.parseInt();
}
digitalWrite(ledPin, HIGH); // turn the LED on (HIGH is the voltage level)
delay(rate); // wait for a second
digitalWrite(ledPin, LOW); // turn the LED off by making the voltage LOW
delay(rate); // wait for a second
}

Resources