Spark Logic

[SOLVED] VCO

ted Wed Sep 05, 2018 1:32 pm

Hi
I am trying to make a VCO based on voltmeter and generator programs, what I need is control Overflow of the timer by voltage applied to PA7.

pwmtimer3.setOverflow(1000 - 1);

Replies

edogaldo Wed Sep 05, 2018 9:33 pm

You should put the timer configuration in the loop, define the overflow value as a function of the input voltage and define the compare value as half of the overflow value.

Cheers, E.

ted Wed Sep 05, 2018 10:27 pm

I did like this, no pulses on PB0

#include <LiquidCrystal.h>
LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5);
HardwareTimer pwmtimer3(3);
int i;
int volt;
void setup() {
pinMode(PA6, INPUT_ANALOG);
lcd.begin(16, 2);
pinMode(PB0, PWM);
/*
pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(72); // Timer input clock Prescaler = 1MHz 72MHz
pwmtimer3.setOverflow(1000 - 1);
pwmtimer3.setCompare(TIMER_CH3, 500); // PWM High Pulse width is 50% duty (1:1)
pwmtimer3.refresh();
pwmtimer3.resume();
*/
}

void loop() {
pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(72); // Timer input clock Prescaler = 1MHz 72MHz
pwmtimer3.setOverflow(i);
pwmtimer3.setCompare(TIMER_CH3, i / 2); // PWM High Pulse width is 50% duty (1:1)
pwmtimer3.refresh();
pwmtimer3.resume();
i == volt;
float volt = analogRead(PA6);
volt = (volt * 3.3) / 4095.0;
lcd.setCursor(0, 0);
lcd.print(volt);
delay(100);
}

RogerClark Thu Sep 06, 2018 1:11 am

I’d recommend you go back to basics

I can’t remember if PB0 even has a timer attached to it, but I’d double check that first

Then just to an AnalogWrite to PB0 and check you get some PWM

After thats working, try setting up your own PWM at one frequency

When thats working and you can set various initial frequencies and check that works

Then in your main(), try setting an initial freq, waiting 250ms and then set a new freq

If at any stage things arent working as you expect, examine what you are doing and bug fix

ted Thu Sep 06, 2018 1:53 am

Everything is working except last two lines, I tried in setup and in the loop.
Then in your main(), try setting an initial freq, waiting 250ms and then set a new freq

If at any stage things arent working as you expect, examine what you are doing and bug fix

#include <LiquidCrystal.h>
LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5);
HardwareTimer pwmtimer3(3);
//int i ;
void setup() {
pinMode(PA6, INPUT_ANALOG);
lcd.begin(16, 2);
pinMode(PB0, PWM);

pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(72); // Timer input clock Prescaler = 1MHz 72MHz
pwmtimer3.setOverflow(1000 - 1);
pwmtimer3.setCompare(TIMER_CH3, 500); // PWM High Pulse width is 50% duty (1:1)
pwmtimer3.refresh();
pwmtimer3.resume();
delay(10);
pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(72); // Timer input clock Prescaler = 1MHz 72MHz
pwmtimer3.setOverflow(100 - 1);
pwmtimer3.setCompare(TIMER_CH3, 50); // PWM High Pulse width is 50% duty (1:1)
pwmtimer3.refresh();
pwmtimer3.resume();

}

void loop() {
/*
pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(72); // Timer input clock Prescaler = 1MHz 72MHz
pwmtimer3.setOverflow(1000 - 1);
pwmtimer3.setCompare(TIMER_CH3, 500); // PWM High Pulse width is 50% duty (1:1)
pwmtimer3.refresh();
pwmtimer3.resume();
delay(10);
pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(72); // Timer input clock Prescaler = 1MHz 72MHz
pwmtimer3.setOverflow(100 - 1);
pwmtimer3.setCompare(TIMER_CH3, 50); // PWM High Pulse width is 50% duty (1:1)
pwmtimer3.refresh();
pwmtimer3.resume();
*/
/*
float volt = analogRead(PA6);
volt = (volt * 3.3) / 4095.0;
lcd.setCursor(0, 0);
lcd.print(volt);
delay(100);
*/
}

edogaldo Thu Sep 06, 2018 7:23 am

Said that you are not waiting for 250ms but for 10, which is the outcome you see?

ted Thu Sep 06, 2018 10:54 am

I put 250 – the same results, only one frequency appears on PB0, when I am using setup frequency is from the this line.
pwmtimer3.setOverflow(100 - 1);

edogaldo Thu Sep 06, 2018 11:37 am

Try this:
#include <LiquidCrystal.h>
LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5);
HardwareTimer pwmtimer3(3);
//int i ;
void setup() {
pinMode(PA6, INPUT_ANALOG);
lcd.begin(16, 2);
pinMode(PB0, PWM);
}

void loop() {
pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(72); // Timer input clock Prescaler = 1MHz 72MHz
pwmtimer3.setOverflow(1000 - 1);
pwmtimer3.setCompare(TIMER_CH3, 500); // PWM High Pulse width is 50% duty (1:1)
pwmtimer3.refresh();
pwmtimer3.resume();
delay(1000);
pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(72); // Timer input clock Prescaler = 1MHz 72MHz
pwmtimer3.setOverflow(100 - 1);
pwmtimer3.setCompare(TIMER_CH3, 50); // PWM High Pulse width is 50% duty (1:1)
pwmtimer3.refresh();
pwmtimer3.resume();
delay(1000);
}

stevestrong Thu Sep 06, 2018 11:38 am

There is already a Timer3 instance of the HardwareTimer(3) defined in the core, and I would suggest you to use that one, and do not declare a new one.
So replace in your code pwmtimer3 with Timer3.

Furthermore, you don’t need to stop and restart the timer each time you change the compare value.
You don’t have to set the prescale factor each time.
It is enough to set it once in the setup
//HardwareTimer pwmtimer3(3); // - not needed

// in setup:
Timer3.setPrescaleFactor(72);
...
// in loop, when you want to change the frequency and/or duty cycle.
...
Timer3.pause();
Timer3.setOverflow(TIMER_CH3, <2*value-1>);
Timer3.setCompare(TIMER_CH3, <value>);
Timer3.refresh();
Timer3.resume();
...

ted Thu Sep 06, 2018 12:32 pm

@ edogaldo
It is working, two frequencies are switching every 1 sec.
blinking LED = blinking generator. :lol:
How this can be used for VCO ?

ted Thu Sep 06, 2018 12:42 pm

@ stevestrong.
I did, like that, and have some errors. Your approach is similar to my in the first post, you changed “i” to “value”, I think will work after removing the errors.
The errors
vco_dc_-stevestrong:16: error: expected initializer before 'void'

void loop() {

^

C:\Users\OWNER\Desktop\vco_dc_-stevestrong\vco_dc_-stevestrong.ino: In function 'void loop()':

vco_dc_-stevestrong:23: error: 'value' was not declared in this scope

value == volt;

^

vco_dc_-stevestrong:26: error: expected primary-expression before '<' token

Timer3.setOverflow(TIMER_CH3, <2*value-1>);

^

vco_dc_-stevestrong:26: error: expected primary-expression before ')' token

Timer3.setOverflow(TIMER_CH3, <2*value-1>);

^

vco_dc_-stevestrong:27: error: expected primary-expression before '<' token

Timer3.setCompare(TIMER_CH3, <value>);

^

vco_dc_-stevestrong:27: error: expected primary-expression before ')' token

Timer3.setCompare(TIMER_CH3, <value>);

^

Multiple libraries were found for "LiquidCrystal.h"
Used: C:\Users\OWNER\AppData\Local\Arduino15\packages\stm32duino\hardware\STM32F1\2018.1.3\libraries\LiquidCrystal
Not used: C:\Users\OWNER\Documents\Arduino\libraries\Newliquidcrystal_1.3.5
Not used: C:\Users\OWNER\Desktop\183\arduino-1.8.3\libraries\LiquidCrystal
Using library LiquidCrystal in folder: C:\Users\OWNER\AppData\Local\Arduino15\packages\stm32duino\hardware\STM32F1\2018.1.3\libraries\LiquidCrystal (legacy)
exit status 1
expected initializer before 'void'

ted Thu Sep 06, 2018 12:44 pm

[stevestrong – Thu Sep 06, 2018 11:38 am] –
how do you verify the resulting frequency on PB0? With a scope?

Yes.

stevestrong Thu Sep 06, 2018 12:55 pm

You forgot to put semicolon to end of line with:
//int i ;
int value // --- missing ";" -----

edogaldo Thu Sep 06, 2018 1:09 pm

Try this:
//http://www.stm32duino.com/viewtopic.php?f=19&t=4082
//edogaldo

#include <LiquidCrystal.h>
LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5);

int ain;
int ovfDiv2;
float volt;

void setup() {
pinMode(PA6, INPUT_ANALOG);
lcd.begin(16, 2);
pinMode(PB0, PWM);
Timer3.setPrescaleFactor(72);
}

void loop() {
ain = analogRead(PA6);
ovfDiv2 = map(ain,0,4095,50,5000); // freq between 100Hz and 10kHz: ain=0 -> freq=100Hz - ain=4095 -> freq=10kHz
Timer3.pause();
Timer3.setOverflow(2*ovfDiv2-1);
Timer3.setCompare(TIMER_CH3, ovfDiv2);
Timer3.refresh();
Timer3.resume();
volt = (ain * 3.3) / 4095.0;
lcd.setCursor(0, 0);
lcd.print(volt);
delay(100);
}

ted Thu Sep 06, 2018 1:52 pm

Frequency changing for voltmeter input 0V to 3.3V
0V – 1.2V = 120Hz-30Hz.
1.2V – 2.7V = no pulses
2.7V – 2.8V = toy music -on speaker
2.8V -3.3V = 200 Hz – 40 Hz

ted Thu Sep 06, 2018 2:26 pm

I changed this line.
//ovfDiv2 = map(ain,0,50,4095,5000); // freq between 10KHz and 100Hz
ovfDiv2 = ain; // freq between 10KHz and 100Hz

edogaldo Thu Sep 06, 2018 2:31 pm

I changed the function later:
ovfDiv2 = map(ain,0,4095,50,5000); // freq between 100Hz and 10kHz: ain=0 -> freq=100Hz - ain=4095 -> freq=10kHz

edogaldo Thu Sep 06, 2018 2:35 pm

Sorry:
ovfDiv2 = map(ain,0,4095,5000,50); // freq between 100Hz and 10kHz: ain=0 -> freq=100Hz - ain=4095 -> freq=10kHz

ted Thu Sep 06, 2018 2:51 pm

0V- 1V = 100Hz, 1V-2V = 200Hz, 2.5V-3.3V 400hz -10000Hz.
Frequency is not much changing for input 0V to 2.5V

ted Thu Sep 06, 2018 3:17 pm

edogaldo
Thanks
I play with the numbers and looks I can get proper response however the sound is not that pure as using VCO build on NE555.
Probably I need averaging “ain”.

stevestrong Thu Sep 06, 2018 3:20 pm

The reversal function is not correct.
You should use this one:
ovfDiv2 = 5050 - map(ain,0,4095,50,5000); // freq between 100Hz and 10kHz: ain=0 -> freq=100Hz - ain=4095 -> freq=10kHz

Sign in to reply