How to stop CAN.onReceive() interrupt?

I wrote a code that interacts with my car can data.

I wish to put the Arduino to sleep when the car if off and no data is transmitted (I need to read information on the bus before the car starts, so I most use the constant 12v to run the Arduino).

I can use the CAN.onReceive(function_name) for waking up the CPU form it sleep mode, but I could not find how to stop the interrupt and allow my normal code to handle the can communication.

I tried CAN.onReceive(null); but it would not compile.
CAN.onReceive(0) would connect the setup to the interrupt.

How should this be done?

#include <CAN.h>

#include <Arduino.h>
#include <avr/sleep.h>

void setup() {
  Serial.begin(9600);
  if (!CAN.begin(1000E3)) {
    Serial.println("Starting CAN failed!");
    Serial.println("Stoping the program!!");
    while (1);
  } 
  Serial.println("CAN connected");
}

long time = millis();

void loop() {
  int packetSize = CAN.parsePacket();       // looks for a package
  if (packetSize) {                     // received a packet
    time = millis();
    // analyze the can command
  }

  if (millis()- time >=3000) {
    Serial.println("  going to sleep");
    sleep_enable();//Enabling sleep mode
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Setting the sleep mode.
    CAN.onReceive(wakeUp);
    CAN.sleep();
    delay(100);
    sleep_cpu();    //activating sleep mode
    Serial.println("just woke up!");    //next line of code executed after the interrupt 
    time = millis();
  }
}


void wakeUp(){
  Serial.println("Interrrupt Fired");//Print message to serial monitor
  sleep_disable();//Disable sleep mode
  CAN.wakeup();
  CAN.onReceive(null);   //<<<< Does not work
}

I found that it should be "NULL" and not "null".
But now when the code constantly returns to the setup!

This is my current code output:

18:03:27.771 -> CAN connected
18:03:30.773 ->   going to sleep
18:03:35.872 -> �k9�connected
18:03:46.790 ->   going to sleep
18:03:50.329 -> InCAN connected
18:04:08.003 ->   going to sleep

Which Arduino and which CAN hardware and which CAN library?

1 Like

You need to be careful of your "power off" current draw, a few mills will kill the battery in short order. Not sure today but one of the requirements was that the car was parked at the airport for two weeks and the the customer expected to get in it and drive it away.

I'm using an Uno, Can shield with MCP2515 and the CAN.h library.

Is it a real uno? How about posting a link to the MCP2515 showing "Technical data" I have several MPC2515 modules and they are different. Which CAN library, there are many? Adding aschematic would help, a frizzy picture would be useless.

hey @ZoharML did u find the solution ? and do someone tell me how CAN.onRecieve() function works ?, is it work as a thread ? i m having repeated output from CAN on my esp can reciever .

Yes, I managed to put the board into sleep and wake from can commands.
It works fine inside my car on a dialy use.
I'ts all inside a big code, So I hope I managed to cut out all the needed code lines:

#include <CAN.h>
#include <avr/sleep.h>  //controls the sleep modes

long last_pid_update= millis();


void setup() {
  Serial.begin(9600);

  if (!CAN.begin(1000E3)) {
    Serial.println(F("Starting CAN failed!"));
    Serial.println(F("Stoping the program!!"));
    while (1);
  } 
  Serial.println(F("CAN connected"));
  last_pid_update=millis(); // allow sleep mode before first pid command
}

void loop() {
  int packetSize = CAN.parsePacket();   // looks for a package
  if (packetSize) {                     // received a packet
    count++;                            // add one for the can command (when the car is off there are hardly any commands).
    last_can_update= millis();
    your code here...
  }
  if ((millis()-last_can_update) >=5*display_Update_time) {  //long time with no can data => time to go to sleep
    Serial.println(F("***__ going to sleep"));
    delay(250);               //wait a bit before the sleep
    sleep_enable();           //Enabling sleep mode
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);  //Setting the sleep mode, in our case full sleep
    CAN.end();                //diconnect from the can library (if not it will not work after the wake)
    attachInterrupt(digitalPinToInterrupt(2), wakeUp, LOW); //attaching a interrupt to pin d2
    delay(50);     //wait a bit before the sleep
    sleep_cpu();    //activating sleep mode
    Serial.println(F("just woke up!")); //next line of code executed after the interrupt 
    last_can_update=millis();     // reset the timeout counter
  }
}

void wakeUp(){      //jump here when can command comes in  sleep
  Serial.println(F("Interrrupt Fired"));  //Print message to serial monitor
  sleep_disable();                            //Disable sleep mode
  detachInterrupt(digitalPinToInterrupt(2)); //Removes the interrupt from pin 2;
  delay (10);
  if (!CAN.begin(1000E3)) {   // reconnect the CAN
      Serial.println(F("Starting CAN failed after sleep"));
      Serial.println(F("Stoping the program!!"));
      while (1);
  } 
  Serial.println(F("CAN connected after sleep"));
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.