little help understanding a program

Hi all, i'm a newbie to programming, so please be kind.
I managed to get the following program running , but had to make a few adjustments.

The first adjustment was line 3.
Should have read 12,11 , not 13,12.

In the description it suggests 4.8 volts to generate 10 hz.
That caused all sorts of problems , moving from 0v to 5v produced the following:

0v---100hz
4.8v-10hz
5v---100hz

Huh!

Second adjustment was line 32
I adjusted 1015 to 1023 and changed the divisor to comply with line 32.

It worked.

Why 1015?

Line 34 , shows count >= 100000
I thought that meant (>) greater than or (=) equal to.

The description clearly describes Pinput as being less < , not > or = .

Any thoughts?

Thanks for listening.

Please post the program here. See General Guidance and How to use the forum

...R

Please, don’t make us get your code on some other URL.

Always, always post ‘your’ code here.

Use CTRL T to format your code.
Attach your ‘complete’ sketch between code tags, use the </> icon in the posting menu.
[code]Paste your sketch here[/code]

Sorry

Robin2 i did spend more than 2-3 reading and thinking and i did get the code working.

larryd i do need clarification and i ask for help , the advice you offered is appreciated , but is all alien to me at

this time----i ask for help

This code is not my sketch and requires the description in the article to understand my questions
I did say at the outset that i am a newbie and an old fart at that.
I am keen to learn all i can----i'm loving the idea of programming and need help.

Again sorry

https://www.engineersgarage.com/knowledge_share/generating-variable-frequency-with-arduino/

Hi larryd , is this right

is this right

Well, you have used code tags, but the idea is to copy the code from your IDE and put that between code tags in a post here

#include <LiquidCrystal.h>
LiquidCrystal lcd(13, 12, 5, 4, 3, 2);
int Pwmpin=9;//Pwm Output Pin
int Fchange= A0;//Frequency change through Potentiometer
//int Button=1;//Button to change the frequency
void setup()
{
lcd.begin(16, 2);  // set up the LCD's number of columns and rows: 
pinMode(Pwmpin, OUTPUT);//Pwm pin as Output
//pinMode(Button, INPUT);//Button as Input
TCCR1A=_BV(COM1A1)|_BV(COM1B1);//Non-inverted Mode
TCCR1B=_BV(WGM13)|_BV(CS11);//Prescalar 8
lcd.setCursor(0, 0);//Lcd Coulomb 0 Row 1
lcd.print("Pwm Period = 50%");
}

void loop(){
float freq=0;
float count=10000,countt=0,Pinput=0;

while(1){
ICR1=count;//variable Frequency
countt=2*8*count;
freq= int(16000000/countt);
OCR1A=int(count/2);
lcd.setCursor(0, 1);//Lcd Coulomb 0 Row 2
lcd.print("Pwm Freq =");
lcd.print(freq);
count=10000;
Pinput=analogRead(A0);//Read input value
Pinput=(Pinput/0.0113);
count=count+Pinput;
if(count>=100000)
  {
    count=10000;
  }
  delay(1000);
}
}

This program did not work as presented.
Two changes had to be made to get it working as claimed.

LiquidCrystal lcd(13,12,5,4,3,2); changed to (12,11,5,4,3,2)

Pinput=(Pinput/0.0113); changed to (Pinput/0.0114)

The first more than likely a typo.
The second was using a value of 1015 for Pinput (as described by the coder)?

Can someone please explain what " if(count>=100000)" means

Thanks

Can someone please explain what " if(count>=100000)" means

If the value of the count variable is greater than or equal to 100000

Probably easier to read if written as

if(count >= 100000)

If you mean what does it do, then if the test is true, the dependant code sets the value of count to 10000. I have not looked at the code enough to know why that test and reset is needed

This code example has a basic error.

ICR1=count;

ICR1 is a 16 bit register with a max value of 65,535. Values greater than this number overfow back to 0 and start counting up again.

In the description it suggests 4.8 volts to generate 10 hz.
That caused all sorts of problems , moving from 0v to 5v produced the following:
0v---100hz
4.8v-10hz
5v---100hz
Huh!

The overflow and resulting small number account for the higher frequency at 5v.

The line "Pinput = (Pinput / 0.0113);" is mapping the 0 to 1023 range of the analog input the a range of 0 to 90,530.9 and when that is added to 10,000 you get a 'count' of 0.0 to 100,530.9. After that any value over 100,000 is set back to 10,000. I think the intent was to have the pot set a frequency between 10 kHz and 100 kHz. It would have been much clearer written as (Pinput * 90000.0) / 1024.0;

With the prescale set to 8 the timer is counting at 2 MHz (16 MHz / 8). To get 10 kHz you need 20,000 toggles per second so you set TOP to 99 to divide the 2 MHz clock by 100. To get 100 kHz you need 200,000 toggles per second so you set TOP to 9 to divide the 2 MHz clock by 10.

void loop()
{
  float frequency = 10000 + (analogRead(A0) * 90000.0) / 1024.0;
  uint16_t TOP = ((F_CPU / 8) / (frequency * 2)) - 1;
  ICR1 = TOP;
  OCR1A = TOP / 2;  // Set period to 50%


  lcd.setCursor(0, 1);//Lcd Coulomb 0 Row 2
  lcd.print("Pwm Freq =");
  lcd.print(frequency, 0);


  delay(1000);
}

It's not clear why whoever wrote that used a prescale of 8. Maybe they were planning to use an 8-bit timer, like Timer2, where TOP can only go up to 255. Since Timer1 is a 16-bit timer and TOP can go up to 65535 it would make sense to use a prescale of 1 and TOP values of 799 and 79 instead of 99 and 9. That would give you 720 steps between 10 kHz and 100 kHz instead of only 90 steps. Using the FastPWM mode would double the toggle rate so TOP would range from 1599 to 159, giving 1440 frequency steps, a good match for the 1024 input steps.

Thanks so much for your replies.
I now have a fully working pwm from 20hz to 20khz

Is it possible to modify this program using two pots to allow the above frequency change and the pulse width ratio to vary from 0 to 100%?

Thanks

Is it possible to modify this program using two pots to allow the above frequency change and the pulse width ratio to vary from 0 to 100%?

Certainly. One pot sets the value of ICR1 for frequency and the other sets the value of OCR1A for duty cycle. With the 0 and 100% values, it may be best to follow the practice of analogWrite() and default to digitalWrite(pin,HIGH) for 100% and digitalWrite(pin,LOW) for 0%.

Hi cattledog , is that a blue heeler.

Great dogs , but you need a big backyard , they never stop.

Ciao

johnwasser:
The line "Pinput = (Pinput / 0.0113);" is mapping the 0 to 1023 range of the analog input the a range of 0 to 90,530.9 and when that is added to 10,000 you get a 'count' of 0.0 to 100,530.9. After that any value over 100,000 is set back to 10,000. I think the intent was to have the pot set a frequency between 10 kHz and 100 kHz. It would have been much clearer written as (Pinput * 90000.0) / 1024.0;

With the prescale set to 8 the timer is counting at 2 MHz (16 MHz / 8). To get 10 kHz you need 20,000 toggles per second so you set TOP to 99 to divide the 2 MHz clock by 100. To get 100 kHz you need 200,000 toggles per second so you set TOP to 9 to divide the 2 MHz clock by 10.

void loop()

{
 float frequency = 10000 + (analogRead(A0) * 90000.0) / 1024.0;
 uint16_t TOP = ((F_CPU / 8) / (frequency * 2)) - 1;
 ICR1 = TOP;
 OCR1A = TOP / 2;  // Set period to 50%

lcd.setCursor(0, 1);//Lcd Coulomb 0 Row 2
 lcd.print("Pwm Freq =");
 lcd.print(frequency, 0);

delay(1000);
}

Thanks for your reply and thanks for (Pinput=(Pinput * 90000/1024)

The intent by the coder was for 10hz t0 100hz.

It never worked from the get go with Pinput=(Pinput/0.0113)

In the code this is the line that confused me.

"if(count>=100000)"

It appears to state that if the count is greater than or equal to 100000 then every is OK.

Not so.

If Pinput is greater than or equal to 90000 then it's kaput.

Is this when syntax becomes semantics?

Any thoughts.

Best regards

Variable Frequency PWM(Pulse Width Modulation) signal generation using Timers of Arduino(Atmega328p Microcontroller)_Arduino Fast PWM.pdf (810 KB)

If Pinput is greater than or equal to 90000 then it's kaput.
Any thoughts.

Many Arduino tutorials and programs found on the internet are incorrect.

spuddo:
In the code this is the line that confused me.

if (count>=100000)

It appears to state that if the count is greater than or equal to 100000 then every is OK.

That is not the whole statement. The whole statement is:

if(count>=100000)
  {
    count=10000;
  }

It is preceded by:

  count=10000;
  Pinput = analogRead(A0);//Read input value
  Pinput = (Pinput/0.0113);
  count = count + Pinput;

So 'count' gets set to a value between 10,000 and 100,530.9 and if the result is 100,000 or more, set it to 10,000.

My guess is that the author intended that 10,000 to be 100,000 so that the upper limit was clipped at 100,000. I can't think of any good reason for values of 100,000 or more to be set to the minimum.