PWM Generation in Arduino uno

Hi Friends
I am using a arduino uno board to Generate a pwm and also program a DAC. The pwm generated by the arduino board is not the expected signal.
Expected PWM signal : high - 34 ms low - 4 microseconds
Generated PWM signal is : high 34ms , low - 600 us .
I am pasting the code below for reference.

#include <Wire.h>                    // Include wire library for I2C communication                      
#include <TimerOne.h> 
void setup()
{
  Serial.begin(9600);
  Wire.begin();
  pinMode(9, OUTPUT);
  pinMode(A4,INPUT_PULLUP);
  pinMode(A5,INPUT_PULLUP);
 
}
 
void loop()
{
 
 pwm();

 byte busStatus;
 
 
 do
  {
    Wire.beginTransmission(0x1C);        //checking the presence of DAC
    busStatus = Wire.endTransmission();  
  }
  while (busStatus !=0x00);               //checking that DAc has aaccepted its address and has sent ACk signal
  Serial.println(busStatus);              //Serial Monitor should show 0
             
 //-------------------------------
  Wire.beginTransmission(0x1C);    //address of DAC 0x1C
  Wire.write(0x08);                //pointing user configurable regsiter
  Wire.write(0x00);  
  Wire.write(0x00);
  Wire.endTransmission();  
  
  
  Wire.beginTransmission(0x1C);           //address of command byte register/load code and load to DAC
  Wire.write(0x01);                    
  Wire.write(0x5D);                       //upper 8-bit data for DAC
  Wire.write(0xC0);                       //lower 8-bit data for DAC
  Wire.endTransmission();

 
}
 
 
 
void pwm ()
{
   digitalWrite(9, LOW);
  delayMicroseconds(4);
  digitalWrite(9, HIGH);
  delay(34);                  // Approximately 10% duty cycle @ 1KHz
 
}

Can you please help me in resolving this issue.

as @Delta_G has said you cant use delay to manage times when you are also running other code.so presently you have

void pwm ()
{
   digitalWrite(9, LOW);  //time signal is LOW
  delayMicroseconds(4);
  digitalWrite(9, HIGH); Make signal high
  delay(34);                  // Approximately 10% duty cycle @ 1KHz
}
.. add more time so signal is high for unknown duration and unknown duty cycle

also 4 microseconds : 34 milliseconds is nowehere near 10%.

Do you NEED a "1kHz" PWM or could you use the 980Hz the Uno natively provides with an Analog Write?

or are you aiming for 4us + 34 us = 40us = 25kHz?

1 Like

Generate a PWM by manually switching pin on and off in the loop - a bad idea at all. But combine it with configuration of DAC and printing to the Serial making the goal of producing correct PWM almost unreachable.
Why did you programmed a DAC in the loop? Do you need program a DAC every 34 ms?

hi
i am trying to generate a pwm with following characteristic
hightime - 34 ms
low time - 4 microseconds

I need to program the DAC only once through the I2C but the wire library triggers the i2c transaction only when called inside a void loop.

it is not a truth. You just do something wrong.
Do you try to move your DAC configuration code to the setup?

It correspond to the duty of 0.01%.
Can you tell us in more detail why you need a PWM with such a small duty? In technical terms, such a sequence is usually called not PWM, but just a single 4us pulse with a interval of approximately 34ms

With what accuracy should these parameters be maintained? For example, if the impulse is not 4us, but 3.125, will this be a problem?
A single 3.125us pulse at 34ms intervals can be programmed using a hardware timer, so it will work independently of the main sketch code.

i Tried calling the wire module in void setup function but DAC was not programmed.

Need to drive a led for a short duration

To drive a led for 4us period? Are you sure?
Could you explain your project in detail?

could you show the code?

By the way, what is your electronic and programming experience?
Did you write this code yourself or did you find and copy a ready-made one?

Are you sure it is 600us?
How are you measuring this pulse?

Measured the pulse in a oscilloscope jim.

hi b707
i am attaching the code that i have used.

#include <Wire.h>                    // Include wire library for I2C communication                      
 
void setup()
{
  Serial.begin(9600);
  Wire.begin();
  pinMode(9, OUTPUT);
  pinMode(A4,INPUT_PULLUP);
  pinMode(A5,INPUT_PULLUP);
 
  Wire.beginTransmission(0x1C);    //address of DAC 0x1C
  Wire.write(0x08);                //pointing user configurable regsiter
  Wire.write(0x00);  
  Wire.write(0x00);
  Wire.endTransmission();  
  Wire.beginTransmission(0x1C);           //address of command byte register/load code and load to DAC
  Wire.write(0x01);                    
  Wire.write(0x5D);                       //upper 8-bit data for DAC
  Wire.write(0xC0);                       //lower 8-bit data for DAC
  Wire.endTransmission();
 

}
 
void loop()
{
 
 pwm();
 
 byte busStatus;
 
 do
  {
    Wire.beginTransmission(0x1C);        //checking the presence of DAC
    busStatus = Wire.endTransmission();  
  }
  while (busStatus !=0x00);               //checking that DAc has aaccepted its address and has sent ACk signal
  Serial.println(busStatus);              //Serial Monitor should show 0
             
 //-------------------------------
 
 
}
 
 
 
void pwm ()
{
  digitalWrite(9, HIGH);
  delayMicroseconds(10);                  // Approximately 10% duty cycle @ 1KHz
  digitalWrite(9, LOW);
  delay(34);
 
}

I did an experiment with an Uno once to see how long a digital write takes... I don't remember the details but I kept a note of the results -

When I wrote high or low, and then the opposite with no delay I got a 3.3uS pulse. (Maybe you can confirm that.) If you add 4uS to that, you should get 7 or 8uS so I don't know where the 600uS is coming from... Or maybe my experiment was wrong and a write takes longer?

After the 30mS delay you are doing other things that will also take some time before you come-back through the loop again.

I agree with @DVDdoug With your last program the pulse should be somewhere between 13us and 16us.

Are you sure your scope is set-up correctly?
Is there anything else connect to pin 9 except the scope?

I agree with both DVDdoug and jim-p.

I measured 3.88µs for a low going pulse using digitalWrite(9, LOW); followed immediately by digitalWrite(9, HIGH);

I haven't got a DAC like yours, so I stripped out all the code relating to the DAC.
This left the following minimal sketch:

void setup()
{
  pinMode(9, OUTPUT);
}

void loop()
{
  digitalWrite(9, LOW);
  delayMicroseconds(10);
  digitalWrite(9, HIGH);
  delay(34);
}

When tested this gave a pulse width in the expected range.

Pulse width = 12.63µs.

I don't think that anything in the original code should affect this delay. Only the 34ms delay should be extended.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.