I'm trying to control an Arduino Barebone from an arduino with relays. Basically when the attiny starts it should switch on the arduino for 4 seconds. The Arduino sends a signal back to a digital pin of the attiny and as long as it is set to high the attiny should leave it working. If it is low the attiny should switch the relay of.
the problem is some changes to the code make the interrupt reset the attiny (which would switch of the arduino) othertimes- in this case. the interrupt doesn't work at all.
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
int pinBoard = 0;
bool boardOn = false;
bool startBoard_flag = false;
int pinBoardReturn = 3;
volatile boolean f_wdt = 1;
void setup() {
cli();//disable interrupts during setup
pinMode(pinBoard, OUTPUT);
pinMode(pinBoardReturn, INPUT);
setup_watchdog(9);
cbi(ADCSRA, ADEN); // switch Analog to Digitalconverter OFF
// cli();//disable interrupts during setup
for (int i = 0; i < 10; i++) {
digitalWrite(pinBoard, HIGH);
delay(100);
digitalWrite(pinBoard, LOW);
delay(100);
}
PCMSK |= (1 << PCINT1); //sbi(PCMSK,INTERRUPTPIN) also works but I think this is more clear // tell pin change mask to listen to pin2 /pb3 //SBI
GIMSK |= (1 << PCIE); // enable PCINT interrupt in the general interrupt mask //SBI
startBoard();
DDRB &= ~(1 << DDB1); //cbi(DDRB, DATADIRECTIONPIN);// set up as input - pin2 clear bit - set to zero
PORTB |= (1 << PB1); //cbi(PORTB, PORTPIN);// disable pull-up. hook up pulldown resistor. - set to zero
}
void startBoard() {
digitalWrite(pinBoard, HIGH);
boardOn = true;
startBoard_flag = false;
cli(); // Disable interrupts
delay(4000);
}
void shutdownBoard() {
digitalWrite(pinBoard, LOW);
boardOn = false;
}
void loop() {
if (f_wdt == 1) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs
f_wdt = 0; // reset flag
if (startBoard_flag) {
startBoard();
}
bool boardReturn = digitalRead(pinBoardReturn);
if (boardOn && !boardReturn) {
shutdownBoard();
}
system_sleep();
}
}
//****************************************************************
// set system into the sleep state
// system wakes up when wtchdog is timed out
void system_sleep() {
// GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts
// PCMSK |= _BV(PCINT3); // Use PB3 as interrupt pin
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement
sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
sleep_cpu(); // sleep
// PCMSK &= ~_BV(PCINT3); // Turn off PB3 as interrupt pin
sleep_disable(); // Clear SE bit
// sei(); // Enable interrupts
}
//****************************************************************
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {
byte bb;
int ww;
if (ii > 9 ) ii = 9;
bb = ii & 7;
if (ii > 7) bb |= (1 << 5);
bb |= (1 << WDCE);
ww = bb;
MCUSR &= ~(1 << WDRF);
// start timed sequence
WDTCR |= (1 << WDCE) | (1 << WDE);
// set new watchdog timeout value
WDTCR = bb;
WDTCR |= _BV(WDIE);
}
//****************************************************************
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
f_wdt = 1; // set global flag
}
ISR(PCINT_VECTOR) {
for (int i = 0; i < 4; i++) {
digitalWrite(pinBoard, HIGH);
delay(1000);
digitalWrite(pinBoard, LOW);
delay(1000);
}
startBoard_flag = true;
f_wdt = 1; // set global flag
}
-
2Sequence like "cli(); delay(...);" is not a very good idea as delay() depends on Timer interrupts.Mikael Patel– Mikael Patel02/24/2016 13:59:52Commented Feb 24, 2016 at 13:59
-
@MikaelPatel Is it? I believe it's just a loop with "NOP" instructions? Wait, this: forum.arduino.cc/index.php?topic=46452.0 - tells me it uses milis, which does use a timer I believe! (AVR delay functions didn't use timers).aaa– aaa02/24/2016 18:27:46Commented Feb 24, 2016 at 18:27
-
@Paul Might a well check the source code. Do you have a link to the ATtiny core that you are using? Let's check delay().Mikael Patel– Mikael Patel02/24/2016 19:08:50Commented Feb 24, 2016 at 19:08
-
So i would rather have a counter for the watchdog in order to wait for the specified time?tinkerly– tinkerly02/24/2016 19:28:48Commented Feb 24, 2016 at 19:28
1 Answer 1
Disassembling the delay
code indicates it uses micros
which needs interrupts on to work.
void delay(unsigned long ms)
{
27a: cf 92 push r12
27c: df 92 push r13
27e: ef 92 push r14
280: ff 92 push r15
282: cf 93 push r28
284: df 93 push r29
286: 6b 01 movw r12, r22
288: 7c 01 movw r14, r24
uint16_t start = (uint16_t)micros();
28a: d3 df rcall .-90 ; 0x232 <micros>
28c: eb 01 movw r28, r22
while (ms > 0) {
28e: c1 14 cp r12, r1
290: d1 04 cpc r13, r1
292: e1 04 cpc r14, r1
294: f1 04 cpc r15, r1
296: 79 f0 breq .+30 ; 0x2b6 <delay+0x3c>
yield();
298: ea d0 rcall .+468 ; 0x46e <yield>
if (((uint16_t)micros() - start) >= 1000) {
29a: cb df rcall .-106 ; 0x232 <micros>
29c: 6c 1b sub r22, r28
29e: 7d 0b sbc r23, r29
2a0: 68 3e cpi r22, 0xE8 ; 232
2a2: 73 40 sbci r23, 0x03 ; 3
2a4: a0 f3 brcs .-24 ; 0x28e <delay+0x14>
ms--;
2a6: 81 e0 ldi r24, 0x01 ; 1
2a8: c8 1a sub r12, r24
2aa: d1 08 sbc r13, r1
2ac: e1 08 sbc r14, r1
2ae: f1 08 sbc r15, r1
start += 1000;
2b0: c8 51 subi r28, 0x18 ; 24
2b2: dc 4f sbci r29, 0xFC ; 252
2b4: ec cf rjmp .-40 ; 0x28e <delay+0x14>
}
}
}
2b6: df 91 pop r29
2b8: cf 91 pop r28
2ba: ff 90 pop r15
2bc: ef 90 pop r14
2be: df 90 pop r13
2c0: cf 90 pop r12
2c2: 08 95 ret
That appears to confirm that the code in wiring.c
is indeed what is being used on the ATtiny85 core:
void delay(unsigned long ms)
{
uint16_t start = (uint16_t)micros();
while (ms > 0) {
yield();
if (((uint16_t)micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
Turning interrupts off and then doing a delay
is a Bad IdeaTM.
So i would rather have a counter for the watchdog in order to wait for the specified time?
Using the watchdog timer is certainly one way of waiting for 4 seconds.
-
Excellent effort and description.Chetan Bhargava– Chetan Bhargava02/25/2016 05:51:40Commented Feb 25, 2016 at 5:51
-
+1 for the Bad Idea(TM). I like it! The rest of the answer deserves it too of course.jfpoilpret– jfpoilpret02/25/2016 12:29:39Commented Feb 25, 2016 at 12:29