Go Down

Topic: Using AltSoftSerial for IR Remote + Sound Sensor (Read 185 times) previous topic - next topic

GlitchReboot

Okay, so I build an sound-activated LED cloud lamp, using a NeoPixel LED strip and the FastLED library. It has various color modes (both static colors and animated modes). All of the individual modes work. The "thunderstorm" mode is the only mode that uses the sound sensor, which triggers "lightning" in the LEDs when it receives a sound above a certain volume.

I've been trying to also implement an IR remote control so that I can switch between the different color modes on the fly, instead of having to change the mode manually in the code and re-upload to the Mega board that I'm using.

The problem is that the IR sensor uses a different baud rate (9600) than the sound sensor (115200). So after much research, I came across both SoftwareSerial and AltSoftSerial libraries. Right now, I'm trying to use the SoftwareSerial library first.

Originally, my pin setup was as follows:
Sound Sensor = A0 (Analog)
IR Sensor = PWM Pin 9
NeoPixel Strand = PWM Pin 7

Everything worked in this setup EXCEPT the IR remote, because I was only initializing the Sound sensor on baud 115200. The IR port wasn't being initialized, which is why I needed to emulate two serial ports. But I can safely say I'm completely lost on how to use either SoftwareSerial or AltSoftSerial libraries to do what I need to do. I'm going to post my currently working code, in which only the Sound sensor is working, but it does have code for the IR remote stuff commented out (as I was testing both individually). I could really use some help, guys. I'm pulling my hair out trying to figure this out.

pylon

Your Mega has 4 (in words: four!) hardware serial interfaces, so there is absolutely no reason to use a software emulation. Throw the horrible SoftwareSerial and the slightly better AltSoftSerial libraries and use the hardware parts.

Are you really sure that your sensors are providing serial data? Post links to the used hardware!

receiveEvent() is called in interrupt context, you must not use any Serial output method in interrupt context! lastMode and mode must be declared volatile if used inside the interrupt handler.

What IR receiver are you using? Are you sure it's providing the data by I2C?

GlitchReboot

#2
Jun 26, 2018, 10:58 pm Last Edit: Jun 26, 2018, 11:40 pm by GlitchReboot
First off, thank you for the reply!

The IR sensor I'm using is a TSOP38238 IR Sensor.
The sound sensor I'm using is a Phantom YoYo Mini.

I would love to be able to just initialize both hardware serial ports without the use of emulation, but I tried that originally and couldn't get both to work together at the same time. I could only get one each one to work by itself individually.

I took a look at Serial Communication on Arduino Reference and it shows what pins are used for RX/TX for each of the serial ports on the Mega. My question about that is, does it actually require the use of USB to Serial adapters? I've attached an image of my wiring diagram (I know it's terrible, it was my first attempt at a wiring diagram). With the code I already attached, and the wiring diagram, the system works perfectly except for the IR not receiving signal from the remote.

I'm still fairly new to Arduino and this is my first major project from scratch (or mostly scratch). So I'm still kinda learning as I go.

So if I change the pins to the ones used by Serial and Serial1, and change my code, it should work then? Should I be using IRrecv, Wire.available(), or could I just use analogRead(PIN) for both? My sound sensor was already coded to use analogRead, cus it's on A0, but not sure if that would still work for the IR sensor.

GlitchReboot

Well, I don't know what I'm doing wrong. I've gotten it to work before and output button presses in HEX to the Serial Monitor, but I don't remember what method I used. I've tried 4 different demo sketches to "decode and print" received button presses to the monitor, and nothing is working. I've tried it on Pin 3,9,11,49 and any other pin I've found reference to regarding the Mega and IRRemote lib. It could be my IR sensor has gone bad, but I don't think that's the case, as it's barely been used and I've only had it for 2 months.

pylon

Quote
I would love to be able to just initialize both hardware serial ports without the use of emulation, but I tried that originally and couldn't get both to work together at the same time. I could only get one each one to work by itself individually.
If you use the Serial, Serial1, Serial2, Serial3 objects, having them working all together is not difficult. Please explain where you had problems.

Quote
The IR sensor I'm using is a TSOP38238 IR Sensor.
The sound sensor I'm using is a Phantom YoYo Mini.
Both have no serial interface. You need special libraries (IRRemote) or analog reads to get signals from these sensors.

Quote
With the code I already attached, and the wiring diagram, the system works perfectly except for the IR not receiving signal from the remote.
Sure, you're trying to read the IR sensor with the Wire library. The Wire library is for the I2C bus but your sensor has a simple digital output and doesn't support any bus system. BTW, according to your wiring diagram you didn't connect the IR sensor to the I2C bus, so why do you use that library?


Quote
So if I change the pins to the ones used by Serial and Serial1, and change my code, it should work then? Should I be using IRrecv, Wire.available(), or could I just use analogRead(PIN) for both? My sound sensor was already coded to use analogRead, cus it's on A0, but not sure if that would still work for the IR sensor.
No, in that setup no serial interface is used (except the PC connection). Forget about serial interfaces. Take a look at the IRRemote library. Get the IR sensor running with a simple sketch that is doing just that task and when it works integrate that code into your bigger sketch.

GlitchReboot

#5
Jul 10, 2018, 02:27 am Last Edit: Jul 10, 2018, 06:54 am by GlitchReboot
If you use the Serial, Serial1, Serial2, Serial3 objects, having them working all together is not difficult. Please explain where you had problems.

Both have no serial interface. You need special libraries (IRRemote) or analog reads to get signals from these sensors.

Sure, you're trying to read the IR sensor with the Wire library. The Wire library is for the I2C bus but your sensor has a simple digital output and doesn't support any bus system. BTW, according to your wiring diagram you didn't connect the IR sensor to the I2C bus, so why do you use that library?


No, in that setup no serial interface is used (except the PC connection). Forget about serial interfaces. Take a look at the IRRemote library. Get the IR sensor running with a simple sketch that is doing just that task and when it works integrate that code into your bigger sketch.

I had it working in a basic sketch that read button inputs from the remote and decoded them, then printed the HEX to the console monitor. And I am using IRRemote libs. The small basic sketch I was using...well I'll just post it. But I uploaded that same sketch to the Mega the other day and it wouldn't work. So I'm wondering if my IR sensor is fried. I wouldn't think so, since I haven't really used it since doing the basic sketch to dump the HEX codes to the remote.

Code: [Select]
#include <boarddefs.h>
#include <IRremote.h>
#include <IRremoteInt.h>
#include <ir_Lego_PF_BitStreamEncoder.h>

int RECV_PIN = 9;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  Serial.println("Ready to decode IR!");
}

void loop() {
  if (irrecv.decode(&results))     {
     Serial.println(results.value, HEX);
     irrecv.resume(); // Receive the next value
    }
}


EDIT: I finally got the above code to work. I had to take the breadboard completely out of the equation and just pin the sensor directly to the mega using female to male cables. Now my sound sensor by itself is not getting power, so I think it's an issue with my breadboard, at least in part. Will update after more testing.

EDIT 2: Okay just running the IR sensor for now. I have it working with my full code, sort of. It's decoding the button inputs from the remote, but it should be the same hex value everytime you press the button. Example: Button 1 should return a hex value of FD08F7. But instead, for some reason, it's returning a random hex value each time I press that button. Same for all the buttons. Here's the monitor output from pressing Button #1 over and over:
Code: [Select]
Receiving IR hex:
Code:
FD08F75
Code:
FFFFFFFF2
Code:
FD08F72
Code:
9C2C5F112
Code:
FD2
Code:
8ADB0D712


I'll post my setup and loop, cus obviously I'm doing something wrong in the code, I just can't figure out what.

Code: [Select]
#include <boarddefs.h>
#include <IRremote.h>
#include <IRremoteInt.h>
#include "FastLED.h"

int RECV_PIN = 9;     // IR sensor output connected to this pin
IRrecv irrecv(RECV_PIN);
decode_results results;

enum Mode {ON,OFF,CLOUD,ACID,FADE,FIRE,SNOW,BLUE,GREEN,RED,PURPLE};
Mode mode = FIRE;
Mode lastMode = FIRE;

void setup() {
  // Starts IR sensor listening
  Serial.begin(9600);            // Serial port for IR sensor
  irrecv.enableIRIn();           // Start IR receiving
  Serial.print("Receiving IR hex: ");
}

void loop() {
  // Here set set the mode based on the IR signal received. Check the debug log when you press a button on your remote,
  // and add the hex codes here (you need 0x prior to each command to indicate it's a hex value)
  if (irrecv.decode(&results)) {
    long int value = results.value;
    Serial.println("Code: ");
    Serial.print(value,HEX);        // Prints the value of the button pressed in HEX format
    Serial.println(mode);           // Prints the name of the mode selected
    irrecv.resume();                // Ready to receive the next HEX value
    lastMode = mode;
    switch(value) {
      case 0xFD00FF:
        mode = ON;break;
      case 0xFD40BF:
        mode = OFF;break;
      case 0xFD08F7:
        mode = CLOUD;break;
      case 0xFD8877:
        mode = FADE;break;
      case 0xFD48B7:
        mode = ACID;break;
      case 0xFD28D7:
        mode = FIRE;break;
      case 0xFDA857:
        mode = SNOW;break;
      case 0xFD6897:
        mode = BLUE;break;
      case 0xFD18E7:
        mode = GREEN;break;
      case 0xFD9867:
        mode = RED;break;
      case 0xFD58A7:
        mode = PURPLE;break;
    }
  }

  // Maps mode names to code functions
  switch(mode) {
    case ON: constant_lightning();reset();break;
    case OFF: reset();break;
    case CLOUD: detect_thunder();reset();break;
    case FADE: colour_fade();break;
    case ACID: acid_cloud();reset();break;
    case FIRE: duckie_fire();reset();break;
    case SNOW: snow_sparkle();reset();break;
    case BLUE: single_colour(CRGB::Blue);break;
    case GREEN: single_colour(CRGB::Green);break;
    case RED: single_colour(CRGB::Red);break;
    case PURPLE: single_colour(CRGB::Purple);break;
    default: detect_thunder();reset();break;
  }
}

pylon

Is it possible that IRremote doesn't know your model of remote control? Have you checked the modulation frequency is correct (= matching your sensor)?

GlitchReboot

#7
Jul 10, 2018, 11:16 pm Last Edit: Jul 10, 2018, 11:24 pm by GlitchReboot
Is it possible that IRremote doesn't know your model of remote control? Have you checked the modulation frequency is correct (= matching your sensor)?
I should have specified. The basic sketch that just decodes and prints out the hex values, just that by itself works fine, prints the hex values correctly like it should. But when I use that same code in my larger loop, that's when it gets screwy.

This is the remote control that I'm using. It came directly from Adafruit, when I bought the sensor. As for checking modulation frequency, I have no idea how to go about doing that, or if I even have the equipment to do it.

pylon

The problem probably lies in the FastLED library. During the data transfer to the NeoPixel LEDs it deactivates interrupts to ensure the strict timing needed. If any IR signal is received in that time frame it's lost and the corresponding code is not recognized.
I guess you have to transfer the IR recognition to a separate processor (an ATtiny is sufficient for that) to enable these two timing critical applications.

GlitchReboot

The problem probably lies in the FastLED library. During the data transfer to the NeoPixel LEDs it deactivates interrupts to ensure the strict timing needed. If any IR signal is received in that time frame it's lost and the corresponding code is not recognized. I guess you have to transfer the IR recognition to a separate processor (an ATtiny is sufficient for that) to enable these two timing critical applications.
Okay so regardless of having the sound sensor, you're saying the remote sensor isn't getting proper signals because of FastLED's timing interrupts? And the best solution would be to put the IR code onto an ATtiny? I could try that and see if that helps things.

I did have a question though. So I have 9 different lighting modes for this project, which is an LED Lamp. The remote was supposed to switch between modes on the fly, which I'm sure you gathered by the code. But only ONE of those modes, "Cloud" actually uses the sound sensor. If I removed that entirely, took out the sound sensor altogether, would it still be possible to get the IR remote working for the other 8 modes without incorporating the ATtiny?

pylon

Quote
Okay so regardless of having the sound sensor, you're saying the remote sensor isn't getting proper signals because of FastLED's timing interrupts?
No, because of FastLED's blocking interrupts.

Quote
And the best solution would be to put the IR code onto an ATtiny?
It doesn't have to be an ATtiny, another Arduino is probably best but an ATtiny would have enough resources to do that.

Quote
If I removed that entirely, took out the sound sensor altogether, would it still be possible to get the IR remote working for the other 8 modes without incorporating the ATtiny?
That problem actually doesn't relate to the sound sensor. That might even pose other problems, I didn't check that.
The problem I described is that IRremote doesn't work well while FastLED is changing LEDs. If the modes would be static (no changing of the LEDs once the mode is chosen), it probably would work but in your case FastLED is constantly updating the LED pixels and during these updates no IR signals are received. That ends in partly received IR commands, which is why your setup don't work.

Go Up