[SOLVED] AnalogWrite() not working

AnalogWrite() doesn't work inside an if loop for PWM pins of the Arduino Nano when receving data via a radio receiver module. Why?

That's your view....

If is not a loop...

You have a bug - don't blame someone else

Good engineers analyze what they do before saying it is not my fault. Very often it is your fault... Make sure you eliminate that.

And post your code....

Here's the code... If I replace the analogWrite() functions within the goForward(), goBackward()..... (all the motor control funcitons) with digitalWrite()..the robot works fine and responds to the change in direction of the transmitter. But I do need to control the speed of the motor based on the data from the sensor.

Bot_code.ino (2.68 KB)

AnalogWrite expects a value between 0 and 255

You are passing int and you don't check the bounds - are you 100% sure what is in the values? Would suggest to print them in your code

Ya i know that... The sensor outputs values within the range 0 to 255 when tilted forward and left. It outputs values from -255 to 0 when tilted backwards or right. For the last case, I can simply add a minus to keep the values in the appropriate range, which I have done already.

I'm doing you a favour and posting in code tags like you should have:

/* Mind controlled car - Car's code */

#include <VirtualWire.h>

int RX_PIN = 11;// Tell Arduino on which pin you would like to receive data NOTE should be a PWM Pin
int RX_ID = 3;// Recever ID address
int TX_ID;

typedef struct roverRemoteData// Data Structure
{
  int    TX_ID;      // Initialize a storage place for the outgoing TX ID
  int    x1;// Initialize a storage place for the first integar that you wish to Send
  int    y1;// Initialize a storage place for the Second integar that you wish to Send
};

void setup() {
  pinMode(5, OUTPUT); //in 1
  pinMode(6, OUTPUT); //in 2
  pinMode(9, OUTPUT); //in 3
  pinMode(10, OUTPUT); //in 4
  Serial.begin(9600);
  vw_setup(2000);// Setup and Begin communication over the radios at 2000bps( MIN Speed is 1000bps MAX 4000bps)
  vw_set_rx_pin(RX_PIN);// Set RX Pin
  vw_rx_start();

}

void loop() {

  struct roverRemoteData receivedData;
  uint8_t rcvdSize = sizeof(receivedData);//Incoming data size
  vw_wait_rx();// Start to Receive data now
  if (vw_get_message((uint8_t *)&receivedData, &rcvdSize)) // Check if data is available
  {
    if (receivedData.TX_ID == RX_ID) //Check if the radio signal recieved matches the ID of the Reciever
    {
      if (((receivedData.x1 < 80) && (receivedData.x1 > -80)) && ((receivedData.y1 < 80) && (receivedData.y1 > -80))) //halt
      {
        halt();
      
      }
      else if (((receivedData.x1 < 80) && (receivedData.x1 > -80)) && (receivedData.y1 > 80)) //forward
      {
        int a = receivedData.y1;
        goForward(a);
       


      }
      else if (((receivedData.x1 < 80) && (receivedData.x1 > -80)) && (receivedData.y1 < -80)) //backward
      {
        int b = -receivedData.y1;
        goBackward(b);
       

      }
      else if ((receivedData.x1 > 80) && ((receivedData.y1 < 80) && (receivedData.y1 > -80))) //left
      {
        int c = receivedData.x1;
        goLeft(c );
        


      }
      else if ((receivedData.x1 < -80) && ((receivedData.y1 < 80) && (receivedData.y1 > -80))) //right
      {
        int d = -receivedData.x1;
        goRight(d);
        


      }
    }
  }
}

void goForward(int y)
{
  analogWrite(5, y);
  analogWrite(6, 0);
  analogWrite(9, y);
  analogWrite(10, 0);
  delay(50);
  

}

void goBackward(int z)
{
  analogWrite(5, 0);
  analogWrite(6, z);
  analogWrite(9, 0);
  analogWrite(10, z);
  delay(50);

}

void goLeft(int w)
{
  analogWrite(5, w);
  analogWrite(6, 0);
  analogWrite(9, 0);
  analogWrite(10, 0);
  delay(50);

}

void goRight(int x)
{
  analogWrite(5, 0);
  analogWrite(6, 0);
  analogWrite(9, x);
  analogWrite(10, 0);
  delay(50);

}

void halt()
{
  analogWrite(5, 0);
  analogWrite(6, 0);
  analogWrite(9, 0);
  analogWrite(10, 0);
  delay(50);

}

I didn't add a delay in the transmitter code. Is that the cause of the problem? :3

Well we don't know the code if the radio sender. (Is the sender sending int?

If you push data super fast you will overflow your input buffer because motors have inertia and you have 50ms delays

So you can loose data and read garbage

I would still suggest to print really what you got and report back

But I do need to control the speed of the motor based on the data from the sensor.

So where is the code that doesn't work?

Here's the serial monitor reading out values (in the attached image). As I have said earlier. The sensor outputs data in the range 0-255 when titlted forward or left side, and -255 to 0 when titled backwards or right side. And here's the transmitter's code:

/* Code for the transmitter of the mind controlled bot */

#include <Wire.h>
#include <ADXL345.h>
#include <VirtualWire.h>

ADXL345 adxl; //variable adxl is an instance of the ADXL345 library
int ledPin = 13; //a sign when the transmitter is working


int TX_PIN = 11;// Tell Arduino on which pin you would like to Transmit data NOTE should be a PWM Pin
int TX_ID = 3; // Transmitter ID address

typedef struct roverRemoteData// Data Structure 
{
int    TX_ID;      // Initialize a storage place for the outgoing TX ID
int    x1;// Initialize a storage place for the first integar that you wish to Send 
int    y1;// Initialize a storage place for the Second integar that you wish to Send
};

void setup() {
  vw_setup(2000);//Bits per second
  pinMode(ledPin,OUTPUT);
  vw_set_tx_pin(TX_PIN);// Set Tx Pin
  Serial.begin(9600);//Initialise the serial connection

  adxl.powerOn(); 

  //set activity/ inactivity thresholds (0-255)
  adxl.setActivityThreshold(75); //62.5mg per increment
  adxl.setInactivityThreshold(75); //62.5mg per increment
  adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?

  //look of activity movement on this axes - 1 == on; 0 == off 
  adxl.setActivityX(1);
  adxl.setActivityY(1);
  adxl.setActivityZ(1);
 
  //look of inactivity movement on this axes - 1 == on; 0 == off
  adxl.setInactivityX(1);
  adxl.setInactivityY(1);
  adxl.setInactivityZ(1);
 
  //look of tap movement on this axes - 1 == on; 0 == off
  adxl.setTapDetectionOnX(0);
  adxl.setTapDetectionOnY(0);
  adxl.setTapDetectionOnZ(1);
 
  //set values for what is a tap, and what is a double tap (0-255)
  adxl.setTapThreshold(50); //62.5mg per increment
  adxl.setTapDuration(15); //625us per increment
  adxl.setDoubleTapLatency(80); //1.25ms per increment
  adxl.setDoubleTapWindow(200); //1.25ms per increment
 
  //set values for what is considered freefall (0-255)
  adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per increment
 
  //setting all interrupts to take place on int pin 1
  //I had issues with int pin 2, was unable to reset it
  adxl.setInterruptMapping( ADXL345_INT_SINGLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_DOUBLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_FREE_FALL_BIT,    ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_ACTIVITY_BIT,     ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_INACTIVITY_BIT,   ADXL345_INT1_PIN );
 
  //register interrupt actions - 1 == on; 0 == off  
  adxl.setInterrupt( ADXL345_INT_SINGLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_DOUBLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_FREE_FALL_BIT,  1);
  adxl.setInterrupt( ADXL345_INT_ACTIVITY_BIT,   1);
  adxl.setInterrupt( ADXL345_INT_INACTIVITY_BIT, 1);
}

void loop()
{
  struct roverRemoteData payload;
  payload.TX_ID = TX_ID; // Set the Radio Address 
  int x, y, z;
  adxl.readXYZ(&x, &y, &z); //read the accelerometer values and store them in variables  x,y,z
  payload.x1 = x;
  payload.y1 = y;
  vw_send((uint8_t *)&payload, sizeof(payload)); // Send the data 
  vw_wait_tx();// Wait for all data to be sent 
  if ((x>80) || (x<-80) || (y>80) || (y<-80))
  {
    digitalWrite(13, HIGH); //ledpin indicator
  }
  else
  {
    digitalWrite(13, LOW);
  }
  delay(100);
  
}

Are you printing on receiver side ?

Why is the ID 0 instead of 3?

Yes, I printed the data out on the receiver side.

The ID is 3.. Not 0.. :confused:

swapnilsayansaha:
Yes, I printed the data out on the receiver side.

The ID is 3.. Not 0.. :confused:

In the image, it prints ID:0

Ok, that's weird, but is that a problem? :confused: The receiver is receiving data from the transmitter. The robot is working smoothly if use digitalWrite() to control the motor motion, immediately changing directions as soon as I change direction of the sensor. :confused: I could get away with it.. But I want the controls to be smooth..

your struct is 48 bits plus overhead and you push input only at 2000 bps so you should write at very max 40 times per second rather than going full speed

50ms for your motor to react is not a lot possibly compared to the rate possibly at which you push the sensor updates

The fact that the ID is wrong means you can't trust the data you receive

Suggest you throttle the data sending side

Or if you received it correctly then ID do not match and your code does nothing

On the throttling while you wait for all the data to go out you are not sure about what happens on the receiver side in buffer

Have you looked at putting a fixed value - say 128 to run at half speed - in analogWrite Instead of doing a digitalWrite?

Fixed the ID.. result's the same.. added some delay...result's the same..

P.S. My bot is working fine.. Except that it is speeding like a Veron.. :3

Yes, I did put in a random speed like 100.. The bot just gets into an infinite loop, it continues to run forever in same direction with only one wheel turning.... If I use digitalWrite, every operation (forward, backward, left, right, stop) works..with the only fact that the speed is quite high

What type of arduino do you have?

Can you write a very small program with just 1 pin and one motor to ensure PWM works with each of the pins you selected ?

Say run 5 sec at half duty (128) and 5 sec at full duty (255)

The PWM feature works... Pins 3,5,6,9,10,11 does show pwm if i just write a simple program like analogWrite(6, 128).... It's an Arduino Nano 3.0... Surprisingly, I have an Arduino Mega 2560, where the analogWrite() function works but the digitalWrite() functon doesn't work,