I'm trying to control a heating element with PWM with an Arduino Nano, but the problem is even if I set the duty cycle to 0 it gives a tiny spike.
I want to generate a square wave of 1Hz and that's why I override the default PWM registers.
Here is the code:
// Set up fast PWM on the Arduino Uno at 1 Hz on digital pin D9
void setup() {
// set I/O pins
pinMode(LDR_INPUT, INPUT); // A0
pinMode(HEATER_OUTPUT, OUTPUT); // D9
// Enable the PWM output OC1A on digital pins 9
TCCR1A = _BV(COM1A1) | _BV(WGM11);
// Set fast PWM and prescaler of 256 on timer 1
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12);
// Set the PWM frequency to 1Hz: 16MHz/(256 * 1Hz) - 1 = 62499
ICR1 = 62499;
// OCR1A = 32149; // this gives me duty cycle of 50%, working fine
OCR1A = 0; // but this is not working
//allow PWM timers to start
delay(10);
}
For testing, I connected an LED to the PWM pin (D9) and these are the spikes from the LDR reading from analog pin A0 (I don't have an oscilloscope).
I'm getting the same results with the Nano and Uno. My IDE version is 1.8.14.
How can I fix this problem?
Here is my temperature control function:
void Compute()
{
unsigned long now = millis();
int timeChange = (now - lastTime);
if(timeChange>=SampleTime)
{
/*Compute all the working error variables*/
double error = Setpoint - temprature;
if (error <= 0)
{
Output = 0;
Serial.println("level: 0");
}
else if (error <= 1)
{
Output = 5;
Serial.println("level: 1");
}
else if (error <= 2)
{
Output = 30;
Serial.println("level: 2");
}
else if (error <= 3)
{
Output = 50;
Serial.println("level: 3");
}
else if (error <= 10)
{
Output = 60;
Serial.println("level: 4");
}
else if (error <= 100)
{
Output = 200;
Serial.println("level: 5");
}
else
{
Output = 255;
Serial.println("level: 6");
}
analogWrite(HEATER_OUTPUT, Output);
//OCR1A = map(Output, 0, 255, 0, 62499);
delay(10);
lastErr = error;
lastTime = now;
}
}
The problem is that after I override the PWM registers, the analogWrite()
seems messed up. It's not working, and for all the values of Output
, the result is almost the same.
UPDATE 22/06/2021
I'm still struggling to fix this, if I use analogWrite()
or digitalWrite()
to turn off the PWM pin, the further changes on OCR1A
regs are not taking action. whatever values I gave to the OCR1A the pin remains low, if I manually make the pin high with digitalWrite or analogWrite the pin remains high forever the changes on OCR1A
are not taking into action.
I wrote a test function
void testPWM3() {
Serial.println("f: 1Hz | on 0s");
digitalWrite(HEATER_OUTPUT, LOW); // turn off the pwm pin to get full of (0% duty cycle)
delay(5000);
/*
After turning off the pin with digitalWrite() further changes on OCR1A reg are not taken into action
*/
digitalWrite(HEATER_OUTPUT, HIGH);
Serial.println("f: 1Hz | on 125ms");
OCR1A = 1953;
delay(5000);
Serial.println("f: 1Hz | on 250ms");
OCR1A = 3906;
delay(5000);
Serial.println("f: 1Hz | on 500ms");
OCR1A = 7812;
delay(5000);
Serial.println("f: 1Hz | on 1sec");
digitalWrite(HEATER_OUTPUT, HIGH); // this works
delay(5000);
}
Any advice on this will be greatly helpful, thank you