1

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
}
Avamander
6242 gold badges11 silver badges35 bronze badges
asked Feb 24, 2016 at 13:53
4
  • 2
    Sequence like "cli(); delay(...);" is not a very good idea as delay() depends on Timer interrupts. Commented 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). Commented 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(). Commented Feb 24, 2016 at 19:08
  • So i would rather have a counter for the watchdog in order to wait for the specified time? Commented Feb 24, 2016 at 19:28

1 Answer 1

4

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.

answered Feb 25, 2016 at 5:28
2
  • Excellent effort and description. Commented 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. Commented Feb 25, 2016 at 12:29

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.