RadioHead library stops after writing to PWM pin

Hi!

I'm using a 433MHz RF receiver and transmitter to send two values (0-1023) from one Arduino nano to another.

I'm trying to use the value (divided by 4) to set the brightness of a LED on the receiving end.

I'm able to receive the sent values properly, but anytime I use analogWrite() to use a PWM pin, I no longer receive new messages. Everything inside ... if (driver.recv(buf, &buflen)) { blablaba }... no longer works, everything outside that part keeps running.

Maybe helpful extra info:

  • When I disconnect the LED pin, I start receiving messages again. When I reconnect, new messages stop.
  • The problem does not occur when I write analog value 0 or 255.
  • The problem also occurs when I send from an Arduino Nano to an Arduino Uno.
  • The problem also occurs at 315MHz
  • I've tried different LED pins, without success: I am aware that RadioHead library uses timer1, so I cannot use pins 9 and 10.
  • I've tried using Timer2 by adjusting the library, also without success.

Any ideas on how to solve this? Thanks for your help in advance!

Receiver code

//Tranceiver pin = 12
//Receiver pin = 11 (HIER)


#include <RH_ASK.h>
#include <SPI.h> // Not actualy used but needed to compile

RH_ASK driver;

int ledPin = 6;
int brightness;

struct dataStruct{
  int value1; 
  int value2;
  unsigned long counter;
}myData;


void setup(){
  Serial.begin(9600);  // Debugging only
  pinMode(ledPin, OUTPUT);
  if (!driver.init())
    Serial.println("init failed");
}

void loop() {
  uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
  uint8_t buflen = sizeof(buf);
  
  if (driver.recv(buf, &buflen)) { // Non-blocking
    int i;
    // Message with a good checksum received, dump it.
    driver.printBuffer("Got:", buf, buflen);
    memcpy(&myData, buf, sizeof(myData));
    Serial.println("");
    
    Serial.print("Value 1:");
    Serial.println(myData.value1);
    
    Serial.print("Value 2: ");
    Serial.println(myData.value2);
    
    Serial.print("Counter: ");
    Serial.println(myData.counter);
    
    brightness = myData.value1 / 4;
    Serial.print("Brightness: ");
    Serial.println(brightness);
  }
  Serial.println(brightness);
  analogWrite(ledPin, brightness);
}

Transmitter code

//Tranceiver pin = 12 (HIER)
//Receiver pin = 11

const int inp_value1 = A0;
const int inp_value2 = A1;

#include <RH_ASK.h>
#include <SPI.h> // Not actually used but needed to compile

RH_ASK driver;

struct dataStruct{
  int value1; 
  int value2;
  unsigned long counter;
}myData;

byte tx_buf[sizeof(myData)] = {0};

void setup(){
  Serial.begin(9600);    // Debugging only
  pinMode(0, INPUT);
  pinMode(inp_value2, INPUT);
  if (!driver.init())
    Serial.println("init failed");
}

void loop(){
  myData.value1  = analogRead(inp_value1);
  myData.value2 = analogRead(inp_value2);
  Serial.print("Value 1: ");
  Serial.println(myData.value1);
  
  memcpy(tx_buf, &myData, sizeof(myData));
  byte len = sizeof(myData);

  driver.send((uint8_t *)tx_buf, len);

  // driver.send((uint8_t *)msg, strlen(msg));
  driver.waitPacketSent();
  myData.counter++;
  delay(500);
}

!

Hello there!

I have some ideas as to the problem, and I must say the "helpful extra info" you posted was intriguing.

First off, each IO pin has several functionalities. For example, pin 6 in your case can either be a digital GPIO, or be connected to the timer and act as a PWM output. The analog pins can also be used as digital IOs if properly configured.

With that said, when you say "analogWrite(6, brightness)" or something along those lines, it changes the functionality of that pin from GPIO to PWM output. That being said, maybe this setting alteration is somehow being sent to all the pins in that port of the microcontroller. This may also indicate why doing an analogWrite of 0 or 255 does not instigate this communication error as the values of these outputs are "digital".

That being said, try to call a "pinMode(ledPin, OUTPUT)" after you do the analogWrite(), which may help to reset the register settings.

Another possibility is that when you initiate your communication protocol, the code inside that library is most likely, (I've never used this library before so bear with me if I am wrong), setting the configuration registers of timer1 inside the microcontroller to control the communication timing. When you call an analogWrite() you are changing these registers to a different setting, which will interfere with the communication protocol.

That being said, is there a way you can re-initialize the communication channel? Perhaps this will reconfigure the timer registers properly.

Finally, I am using a similar set of components for an RC car that I am making, and research and experimentation has proved that the VirtualWire library, the predecessor to RadioHead, works with sending PWM signals as well as using the ServoTimer2 library, so perhaps look into this if RadioHead does not work for you.

Sorry for the long reply

bos1714 - you don't seem to have an understanding of the internals you're talking about. No offense, but like, you're not helping...

analogWrite() on one pin does not change behavior of any other pins (unless that timer had been reconfigured for some other use, and that was impacted by the analogWrite - but OP's code clearly does not do that). It certainly doesn't screw up the rest of the port.
analogWrite() already calls pinMode to set the pin output (which is bloody stupid imo).

analogWrite() on the pins for the timer used by radiohead will, as OP knows, break it. But he's not doing that - I might try pins on timer0... (just to rule out the possibility that it's actually using timer2 for RH, not timer1). But see below - I don't think it has anything to do with the code.

I think the first mentioned oddity is the really important one - disconnecting led pin makes it work again. So you're saying that if you've analogWritten a value to that pin, with the LED connected, it won't receive anything... but if you disconnect the LED, running the exact same code, it does continue to receive? Am I understanding that correctly?

If this is the case, it has nothing to do with the code, because it works with the same code it fails with, depending on whether an LED is connected. In that case - it's a hardware problem. If so...

Maybe EMI? That's pretty sad if the EMI from a 20mA LED being PWM'ed is enough to break them - but if that's what's doing it, some of my experiences with those terrible receivers make more sense.

Those particular RF receivers are absolute trash, totally unfit for any purpose. Get an RXB12, little yellow PCB like $1 shipped on ebay. They are much more reliable, much better over wider range of input voltage, and 10-20 times the range of those ubiquitous green ones. The green transmitters that come with those terribad receivers are fine (though the STX882 gives slightly better range at 3.3v). Try it with an RXB12 (assuming

Thanks both @Bos1714 and @DrAzzy for your thoughts and suggestions. I appreciate it!
@DrAzzy, your post stops mid-sentence: did you accidentally leave out any important suggestions?

Reactions on your remarks/ questions:

Those particular RF receivers are absolute trash, totally unfit for any purpose.

I guess you get what you pay for :slight_smile:

but if you disconnect the LED, running the exact same code, it does continue to receive? Am I understanding that correctly?

That’s correct. No need to reset or anything, just pulling the plug results in the messages being printed again.

I've now tried the following:

  • Connecting the LED to pin 3, 5, 6, 9, 10
  • Calling pinMode(ledPin, OUTPUT); after analogWrite();
  • Building an 'Aluminium hat' (see pictures) around the transmitter & receiver. Not sure if that would help against Electro Magnetic Interference (EMI), felt silly, but worth the long shot.
  • The virtual wire library

Alas, none of these suggestions worked. They all had the exact same result as described above (with the exception of using pin 9 or 10, which stopped the complete program).

  • I also ordered RBX12 receivers. They're obviously not here yet, so I haven't been able to test if this is a solution. Will update & test once I get them.

Any other thoughts in the meantime?
Nobody else with this experience?

Without aluminium 'hat'

With aluminium 'hat' in an unsuccessful attempt to block potential EMI.

Those particular RF receivers are absolute trash,

No, they work fine if you observe their limitations. I've been using them for nearly 10 years. They are found in millions of commercial remote controlled devices, home weather stations, etc. The superregenerative versions are not quite as sensitive as the superheterodyne versions.

@OP forget the aluminum hat and put antennas on TX and RX, 17 cm of straight wire.

Put RX and TX, with their associated Arduinos, on separate circuit boards as well. Make sure all power and ground leads are properly connected.

Start with the VirtualWire library and the simple examples that come with it, and get those working first. It uses Timer1, so you will have to solve that problem (by changing a compiler option), after you get communications working.

It works now! :slight_smile:

It worked after trying this suggestion:

put antennas on TX and RX, 17 cm of straight wire.

(I first tried the other suggestions without succes: )

  • Separate breadboards
  • Using RadioHead Library and the VirtualWire library

Strangely enough, it kept working after removing the antenna's. I don't understand that.
But anyway... Happy it works now :slight_smile:

But thanks jremington, DrAzzy & bos1714 for your suggestions!