Sending PWM over 433MHz

I know this is likely a simple fix, I’ve seen questions related to this before but none seem to resolve the issue that I am having. So in a nutshell I have a potentiometer on one arduino and an RGB LED on the other. I’m taking the analogRead() value and sending it across to analogWrite how red the LED is so that I can make sure I can control the signal properly to do things later. Simple enough task and here is the receiver code that I am using:

#include <VirtualWire.h>

int red_pin = 9;
int red;


void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);

  vw_setup(2400);
  vw_set_rx_pin(5);
  vw_rx_start();

  pinMode(13, OUTPUT);
  analogWrite(red_pin, 255);
  digitalWrite(13, HIGH);
  
}

void loop() {
  // put your main code here, to run repeatedly:

  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if(vw_get_message(buf, &buflen)){
    Serial.println("Received Message: ");
    Serial.println(buf[0]);
    Serial.println(int(buf[0]));
    Serial.println(analogRead(5));
    
    int i;    
    digitalWrite(13, LOW);
    
    for( i=0 ; i < buflen ; i++){
      Serial.println(buf[i]);
      red = map(buf[i], 0, 512, 0, 255);
      analogWrite(red_pin, 255 - red);
    }
    digitalWrite(13, HIGH);
  }
}

The issue is that the analogWrite() seems to be cutting off the transmission in a way. In the Serial Monitor you can see that the buf i values just stop printing after a short amount of time and nothing adjusts. I’m pointing the finger at the analogWrite() because when I comment it out then I can print signals all day long with no issue. I’ve looked everywhere and referenced the documentation for VirtualWire.h and can’t seem to find anything else to try. Any suggestions would be greatly appreciated.

(deleted)

First of all, thank you for asking a well written question. You explain the problem, show the sketch, and most important: you already gave the answer. Well, almost ;)

The analogWrite() to pin 9 or pin 10 uses Timer1. The VirtualWire library uses Timer1. There's your problem.

Could you try PWM on pin 5, 6 (Timer0) or 11, 3 (Timer2) ?

The VirtualWire uses three pins. All three of them are set to a default pin in the library, even if you did not assign them to a pin. I suggest to use all the vw_set_rx_pin(), vw_set_tx_pin(), vw_set_ptt_pin() and assign them to unused pin if you don't need them. Explain in the comments all the pins of your project.

P.S.: You can use "Quick Edit" or "Modify" to edit your post and fix the buf [ i ]

As others have noted, you need to check that there is data in the buffer. You're sending a single byte, but you're looping through a lot more than 1 byte....

red = map(buf[i], 0, 512, 0, 255);

buf is an array of bytes. A byte can have a value between 0 and 255.

So why are you taking a value 0~255, but mapping it as if it's 0~512?

Also, why are you using map at all in any case? Just rightshift it 1 and get the same effect as that map() call.

Koepel - switching pins fixed the problem initial problem of the transmission completely stopping so thank you!!

DrAzzy - This is the first time i've used wireless communication of any sort and never used data at the byte level. I have however used multiple Arduinos connected together, so is what you're suggesting similar to Serial.available or something along those lines. Bitshift never occurred to me because I have never used it, but I am assuming that will fix the issue of the LED flickering since the values output in the buf i array seem to be somewhat random. Any info would be helpful!

To follow up, I seem to have fixed it (sort of) from my transmitter code. May not be the correct or most efficient solution so I am always open to other ideas.

Code before:

#include <VirtualWire.h>

int button;
int dial = A0;
int pot_val;
char *msg;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  vw_setup(2400);
  vw_set_ptt_inverted(true);
  vw_set_tx_pin(9);

  pinMode(4,INPUT);
  digitalWrite(13, LOW);
  digitalWrite(4, HIGH);
  
}

void loop() {
  digitalWrite(13, HIGH);
  pot_val = analogRead(dial);
  msg = char(pot_val);
  vw_send((uint8_t*)msg, strlen(msg));
  vw_wait_tx();
  digitalWrite(13, LOW);
}

Code after:

#include <VirtualWire.h>

int button;
int dial = A0;
int pot_val;
char *msg;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  vw_setup(2400);
  vw_set_ptt_inverted(true);
  vw_set_tx_pin(9);

  pinMode(4,INPUT);
  digitalWrite(13, LOW);
  digitalWrite(4, HIGH);
  
}

void loop() {
  digitalWrite(13, HIGH);
  pot_val = analogRead(dial);
  char msg[1] = {pot_val}; //changed len of array to send
  vw_send((uint8_t*)msg, 1);
  vw_wait_tx();
  digitalWrite(13, LOW);
}

Might be a band-aid fix but it seems to work, so if there is a better way I’m open to suggestions

ethanh9: Koepel - switching pins fixed the problem initial problem of the transmission completely stopping so thank you!!

DrAzzy - This is the first time i've used wireless communication of any sort and never used data at the byte level. I have however used multiple Arduinos connected together, so is what you're suggesting similar to Serial.available or something along those lines. Bitshift never occurred to me because I have never used it, but I am assuming that will fix the issue of the LED flickering since the values output in the buf i array seem to be somewhat random. Any info would be helpful!

Bitshift is unrelated to the flickering. It is just an equivalent - but faster+smaller way to replace division by a power of 2 (which, last I checked, pulls in the software division code (there's no hardware division on 8-bit AVRs)). And map (a,0,nx,0,mx) where n and m are powers of 2 and x is any integer) can be replaced by multiplication or division by a power of 2, hence by bitshifts.

I'd wager that the "flickering" could be caused by your reading a whole bunch of bytes from the array when you've only sent one. What do you expect all those other bytes to mean? You're assigning what... 32? 64? different values to the pwm duty cycle in rapid succession, so it only spends much time at the value of the last byte in the array - this seems totally wrong and nonsensical. Review the VW documentation - I don't use vw so I don't know off the top of my head what the buffer gets populated with and how to interpret it, but the way you are doing it can't be right.