0

RCSwitch ReceiveDemo_Simple Interrupt
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

RCSwitch ReceiveDemo_Simple Interrupt

by LEDLIT1 on Sat Jan 16, 2021 5:37 pm

Using my Arduino Uno, when I run the ReceiveDemo_Simple from the RCSwitch library, I can see info received in the serial monitor when I press any button on my RF remote. It works.

The problem I am having is receiving RF data while the Arduino Uno is controlling something else, like an LED animation. It doesn't show any response in the serial monitor other than the cylon "x". I thought that because the RCSwitch utilized interrupt 0 on pin #2 that button presses would not be missed, but I was mistaken.

Is there a way I can code this so I don't miss a button press using RCSwitch while other things are running?

Here is the code below.

Code: Select all | TOGGLE FULL SIZE
// RCSwitch ReceiveDemo_Simple with FastLED cylon

#include <FastLED.h>
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
#define DATA_PIN            6   // LED strip DATAPIN
#define NUM_LEDS 85
CRGB leds[NUM_LEDS];

void setup() {
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
  LEDS.addLeds<WS2813, DATA_PIN, RGB>(leds, NUM_LEDS);
  LEDS.setBrightness(84);
}

void ReceiveDemo_Simple () {
  if (mySwitch.available()) {

    Serial.print("Received ");
    Serial.print( mySwitch.getReceivedValue() );
    Serial.print(" / ");
    Serial.print( mySwitch.getReceivedBitlength() );
    Serial.print("bit ");
    Serial.print("Protocol: ");
    Serial.println( mySwitch.getReceivedProtocol() );

    mySwitch.resetAvailable();
  }
}

void cylon() {
  static uint8_t hue = 0;
  Serial.print("x");
  // First slide the led in one direction
  for(int i = 0; i < NUM_LEDS; i++) {
    // Set the i'th led to red
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(10);
  }
  Serial.print("x");

  // Now go in the other direction. 
  for(int i = (NUM_LEDS)-1; i >= 0; i--) {
    // Set the i'th led to red
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(10);
  }
}

void fadeall() {
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i].nscale8(250);
  }
}

void loop() {
  ReceiveDemo_Simple();
  cylon();
}


LEDLIT1
 
Posts: 89
Joined: Mon Oct 17, 2016 11:14 am

Re: RCSwitch ReceiveDemo_Simple Interrupt

by adafruit_support_bill on Sat Jan 16, 2021 6:02 pm

Neopixels have extremely tight timing requirements. I'm not familiar with the FastLed implementation, but I'd expect that they need to disable interrupts during writes to the pixels.

adafruit_support_bill
 
Posts: 80362
Joined: Sat Feb 07, 2009 10:11 am

Re: RCSwitch ReceiveDemo_Simple Interrupt

by LEDLIT1 on Sat Jan 16, 2021 6:07 pm

Thank you. I'll try disabling the interrupts during write to pixels and tell you how it went.

LEDLIT1
 
Posts: 89
Joined: Mon Oct 17, 2016 11:14 am

Re: RCSwitch ReceiveDemo_Simple Interrupt

by adafruit_support_bill on Sat Jan 16, 2021 6:13 pm

I suspect that they already are, and that is why you are missing your button interrupts.

adafruit_support_bill
 
Posts: 80362
Joined: Sat Feb 07, 2009 10:11 am

Re: RCSwitch ReceiveDemo_Simple Interrupt

by LEDLIT1 on Sat Jan 16, 2021 6:59 pm

I tried disabling and enabling before and after write to pixels, but still no response. If I only run ReceiverDemo_Simple, it works great.

I tried receiving RF with Neopixel "Strandtest", but still not response when I try to receive RF while in the main loop. Please see code strandtest_with_ReceiveDemo_Simple .

Is there a way to store the data received into a cue when the interrupt is triggered?
Like in a thread or something like that, but I am not sure how to do that. I have read the "Multi-tasking the Arduino" several times, but I can't figure out to use that method with RCSwitch. Also, because RCSwitch attaches the interrupt and uses its handler in the h file and cpp files, I am not clear how to approach resolving this without altering the library in some way.


Code: Select all | TOGGLE FULL SIZE
// A basic everyday NeoPixel strip test program.
// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
//   connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
//   a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)

#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN    6

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 85

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)


// setup() function -- runs once at startup --------------------------------

void setup() {
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
  Serial.println("RCSwitch On ");
 
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}

void ReceiveDemo_Simple () {
  if (mySwitch.available()) {

    Serial.print("Received ");
    Serial.print( mySwitch.getReceivedValue() );
    Serial.print(" / ");
    Serial.print( mySwitch.getReceivedBitlength() );
    Serial.print("bit ");
    Serial.print("Protocol: ");
    Serial.println( mySwitch.getReceivedProtocol() );

    mySwitch.resetAvailable();
  }
}

// loop() function -- runs repeatedly as long as board is on ---------------

void loop() {
  ReceiveDemo_Simple ();
 
  // Fill along the length of the strip in various colors...
  colorWipe(strip.Color(255,   0,   0), 50); // Red
  colorWipe(strip.Color(  0, 255,   0), 50); // Green
  colorWipe(strip.Color(  0,   0, 255), 50); // Blue

  // Do a theater marquee effect in various colors...
  theaterChase(strip.Color(127, 127, 127), 50); // White, half brightness
  theaterChase(strip.Color(127,   0,   0), 50); // Red, half brightness
  theaterChase(strip.Color(  0,   0, 127), 50); // Blue, half brightness

  rainbow(10);             // Flowing rainbow cycle along the whole strip
  theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant
}


// Some functions of our own for creating animated effects -----------------

// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
  for(int a=0; a<10; a++) {  // Repeat 10 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in steps of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show(); // Update strip with new contents
      delay(wait);  // Pause for a moment
    }
  }
}

// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this outer loop:
  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
    for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
      // Offset pixel hue by an amount to make one full revolution of the
      // color wheel (range of 65536) along the length of the strip
      // (strip.numPixels() steps):
      int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
      // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
      // optionally add saturation and value (brightness) (each 0 to 255).
      // Here we're using just the single-argument hue variant. The result
      // is passed through strip.gamma32() to provide 'truer' colors
      // before assigning to each pixel:
      strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
    }
    strip.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;     // First pixel starts at red (hue 0)
  for(int a=0; a<30; a++) {  // Repeat 30 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in increments of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        // hue of pixel 'c' is offset by an amount to make one full
        // revolution of the color wheel (range 65536) along the length
        // of the strip (strip.numPixels() steps):
        int      hue   = firstPixelHue + c * 65536L / strip.numPixels();
        uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show();                // Update strip with new contents
      delay(wait);                 // Pause for a moment
      firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
    }
  }
}

LEDLIT1
 
Posts: 89
Joined: Mon Oct 17, 2016 11:14 am

Re: RCSwitch ReceiveDemo_Simple Interrupt

by adafruit_support_bill on Sat Jan 16, 2021 7:44 pm

As I explained above, interrupts are likely disabled when writing to the pixels. Since your loop is continuously writing to the pixels, interrupts are continuously disabled.
When interrupts are disabled, you cannot receive interrupts. So you cannot get button interrupts while in your loop.

adafruit_support_bill
 
Posts: 80362
Joined: Sat Feb 07, 2009 10:11 am

Please be positive and constructive with your questions and comments.