Go Down

Topic: WDT Nano with L298N for dc motor (Read 1 time) previous topic - next topic

Marciokoko

#15
Sep 26, 2018, 10:54 pm Last Edit: Sep 26, 2018, 11:04 pm by Marciokoko
Ok nevermind, I didnt plug in the 9V source, I had just left the USB connected to the computer so maybe it wasnt getting enough juice, which is btw why it should 4.85V or so, instead of the 8.45V.

I did discover however that a cleaned-up version of my code didnt work, seems the nano is reboots, maybe the wdt_reset() isnt reached in time, and so the runMotor() is never called.  But with my old sleep code it works fine.  So Id like to ask for help in cleaning up that failing code.  Below are both code versions and both video links:

GOOD CODE======================================================
Code: [Select]

#include <avr/wdt.h>            // library for default watchdog functions
#include <avr/interrupt.h>      // library for interrupts handling
#include <avr/sleep.h>          // library for sleep
#include <avr/power.h>          // library for power control
#include <util/delay.h>


//1. DEFINE LED PIN FOR COND COMP
#if (defined (__AVR_ATmega328P__) || defined (__AVR_ATmega328__))
    #define UNO
    #define LED_PORT        PORTB
    #define LED_PIN         PB5
    char BOARD[]      = {"m328p"};
#endif

//2. Defines variables
#define LED 13
#define fet 5
int nbr_sleeps=0;
int enA = 10;
int in1 = 7;
int in2 = 6;
 
inline void     flash_led()     {LED_PORT |= (1 << LED_PIN); _delay_ms(30);
                                    LED_PORT &= ~(1 << LED_PIN);}


//3. Interrupt Service Routine - disable wdt as soon as comeback
ISR(WDT_vect){
        // disables wdt upon wake up so it wont fire accidentally while we do stuff before sleep again
        wdt_disable();
        //does it get re-enabled by sleep_mode()?  wdt_reset() might be a better idea.
}

//5. Set some other stuff up in setup
void setup(){
  //5.1 L298N setup
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);   
  pinMode(fet, OUTPUT);
  digitalWrite(fet, LOW);
  pinMode(LED, OUTPUT);
}

//6. These must be called each loop
void sleep(){
   nbr_sleeps ++;
   MCUSR &= ~(1<<WDRF); //or MCUSR = 0;
   ADCSRA = 0; //turns off ADC
   WDTCSR |= (1<<WDCE) | (1<<WDE); //or WDTCSR = bit (WDCE) | bit (WDE);
   WDTCSR = 1<<WDP0 | 1<<WDP3;// or WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0);
   WDTCSR |= _BV(WDIE);
   wdt_reset();
   set_sleep_mode(SLEEP_MODE_PWR_DOWN); 
   noInterrupts();
   sleep_enable();
   // turn off brown-out enable in software
   MCUCR = bit (BODS) | bit (BODSE);
   MCUCR = bit (BODS);
   interrupts();             // guarantees next instruction executed
   sleep_mode();
   flash_led();
   //EXECUTION AFTER ISR RESUMES HERE...
   sleep_disable();
}
void loop(){
  flash_led(); //signalling about to sleep
  sleep(); //sleep suff
  if (nbr_sleeps==4) runMotor();
}
//8 sec/cycle * 450 cycles = 3600 seconds = 1hr


void runMotor() {
  //Turn motor on
  flash_led(); //signal about to run motor
  //turn on mosfet
  digitalWrite(fet, HIGH);
  delay(500);
  //Now run motor
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  analogWrite(enA, 200);
  delay(2000);
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(fet, LOW);
  nbr_sleeps=0;
}


BAD CODE=========================================================
Code: [Select]

#include <avr/wdt.h>            // library for default watchdog functions
#include <avr/interrupt.h>      // library for interrupts handling
#include <avr/sleep.h>          // library for sleep
#include <avr/power.h>          // library for power control
#include <util/delay.h>


//1. DEFINE LED PIN FOR COND COMP
#if (defined (__AVR_ATmega328P__) || defined (__AVR_ATmega328__))
    #define UNO
    #define LED_PORT        PORTB
    #define LED_PIN         PB5
    char BOARD[]      = {"m328p"};
#endif

//2. Defines variables
#define LED 13
#define fet 5
int nbr_sleeps=0;
int enA = 10;
int in1 = 7;
int in2 = 6;
 
inline void     flash_led()     {LED_PORT |= (1 << LED_PIN); _delay_ms(30);
                                    LED_PORT &= ~(1 << LED_PIN);}


//3. Interrupt Service Routine - disable wdt as soon as comeback
ISR(WDT_vect){
        // disables wdt upon wake up so it wont fire accidentally while we do stuff before sleep again
        wdt_disable();
        //does it get re-enabled by sleep_mode()?  wdt_reset() might be a better idea.
}
//4. Set WDT config parameters - ONCE
void configure_wdt(){
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   
    MCUSR &= ~(1<<WDRF); //or MCUSR = 0;
    ADCSRA = 0; //turns off ADC
    power_adc_disable() //PRR extras
    SPCR = 0; //turns off spi
    power_spi_disable();// turns off clock to spi PRR extras
    power_all_disable(); // PRR extras
    WDTCSR |= (1<<WDCE) | (1<<WDE); //or WDTCSR = bit (WDCE) | bit (WDE);
    WDTCSR = 1<<WDP0 | 1<<WDP3;// or WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0);
    WDTCSR |= _BV(WDIE);
}

//5. Set some other stuff up in setup
void setup(){
  //5.1 L298N setup
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);   
  pinMode(fet, OUTPUT);
  digitalWrite(fet, LOW);
  pinMode(LED, OUTPUT);
  configure_wdt();
}

//6. Could maybe move some parameters, like ADC off back into the sleep()-loop()
void sleep(){
   nbr_sleeps ++;
   wdt_reset();
   sleep_mode();
  //EXECUTION AFTER ISR RESUMES HERE...

}
void loop(){
  flash_led(); //signalling about to sleep
  sleep(); //sleep suff
  if (nbr_sleeps==4) runMotor();
}
//8 sec/cycle * 450 cycles = 3600 seconds = 1hr


void runMotor() {
  //Turn motor on
  flash_led(); //signal about to run motor
  //turn on mosfet
  digitalWrite(fet, HIGH);
  delay(500);
  //Now run motor
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  analogWrite(enA, 200);
  delay(2000);
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(fet, LOW);
  nbr_sleeps=0;
}


Video Links:
http://www.youtube.com/watch?v=vOzZX1nRG6M

The bad video is similar but the led would blink before 8 seconds of sleep in one of the cycles, leading me to believe the Arduino was rebooted.

silly_cone

glad it was easy.

just to clarify, if you remove all the sleep-code and use a stripped-down program, do the motors behave as you intend?

Marciokoko

Yes the code without sleep (using mills every 8 seconds) works fine.

But I made a compilation of sleep code snippets which works and it's the one used in the uploaded video.

But then I made a newer version of the sleep code where I tried moving somethings I thought were fine inside a one-time called function named configure_wdt() and other calls which I thought could be called every loop/sleep time but that code didn't work, that's the one called bad code.

What I wanted was to use a complete and clean version of my sleep codebut it doesn't work. 

Marciokoko

1.  Things not in bad code:
A noInterrupts
B sleep_enable()
C MCUCR BODS
D Interrupts()

2. Differences in order:
A flash_______________|set_sleep_mode
B nbr________________|Mcucsr/Adcsra
C Mcucsr/Adcsra/Wdtcsr_|power_adc_disable/Spcr
D wdt_reset_________|power_spi_disable/power_all_disable
E set_sleep_mode__|Wdtcsr
F Interrupts/Bods__|flash_led()
G sleep_mode_____|nbr
H flash_led()______|wdt_reset()
I sleep_disable_____|sleep_mode()

So I tracked down the issue to calling power_all_disable() without calling power_all_enable() again afterwards.

Thanks

Marciokoko

#19
Jan 11, 2019, 09:28 pm Last Edit: Jan 11, 2019, 09:31 pm by Marciokoko
Hey guys, Im back with trouble here.  I moved over from breadboard to through hole.  I cant seem to make the motor run anymore.  The same setup worked on the breadboard but now fails to run the motor.  

I know the code is fine because it worked before (on the breadboard).  Here is the diagram:



I read the voltage between the D5 pin on the nano and GND and I get 5V on the multimeter, so I know the pin on the nano is being set to HIGH as expected.  

I read the voltage between 12V of the L298 and the GND of L298 and I get 0 when nano-D5 goes high.

I read the voltage between GND and Mosfet Gate and I get 5V when nano-D5 goes high.  

So it must be something else.  Here are the images of my board:



outsider

BSS97? That old relic is not logic level and only rated 1.5 Amps, don't you have a mosfet from this century?

Go Up