Moderators: Dave Moll, Andrew Davie, Steve Anderson
// A sketch that creates an 8MHz, 50% duty cycle PWM and a 250KHz,
// 6bit resolution PWM with varying duty cycle (changes every 5μs
// or about every period.
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
pinMode(3, OUTPUT); // output pin for OCR2B
pinMode(5, OUTPUT); // output pin for OCR0B
// Set up the 250KHz output
TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS20);
OCR2A = 63;
OCR2B = 0;
// Set up the 8MHz output
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
TCCR0B = _BV(WGM02) | _BV(CS00);
OCR0A = 1;
OCR0B = 0;
// Make the 250KHz rolling
while (1) {
_delay_us(5);
if ( OCR2B < 63 )
OCR2B += 5;
else
OCR2B = 0;
}
}
Klaas Robers wrote:Don't use the 1N4004, it is definitely too slow.
// CURRENTLY DOING 62.5K with max 255 counter.
// CAUTION: Uses Timer0 which can interfere with operation of delay() and other time-based operations/functions.
#define MOTOR_PIN 11
void setup() {
pinMode(11, OUTPUT);
// Set up the 62.5KHz output, scalar of 1
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
TCCR0B = _BV(CS00);
OCR0A = 0; // duty cycle (0-255)
OCR0B = 0;
// Debug
Serial.begin(9600);
while (! Serial);
Serial.println("Duty? (0-255)");
}
void loop() {
if (Serial.available()) {
int duty = Serial.parseInt();
OCR0A = duty;
Serial.print(duty);
}
}
Klaas Robers wrote:1 kHz is not really much higher than the 500 Hz first. If you go to 20 kHz you will see the first 5% of the wave forms that you see now in your last pictures. That is almost a square wave.
I would suggest to make the frequency somwhere between 16 kHz and 32 kHz. If you have 62 kHz it should also be possible to choose 31 kHz or 15.5 kHz. That is a decent frequency for PWM in a motor. May be you then have 512 steps or 1024, also not bad for the resolution. And now I see that your oscilloscope is really too low frequent to show the wave forms.
I got the impression that you bought 10 years ago, for your first monitor, a hardware oscilloscope... It that one still running? That should be able to give much better wave forms. Yes, it might be a big beast, but after you have done, you may put it again where it was.
// PWM testbed
// Creates a PWM on an output pin
void setup() {
// Only enable the pin that's being used. Here are all the options for the Micro though...
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(13, OUTPUT);
// Setup the PWM
// WGM02|WGM01|WGM00 = waveform generation
// = fast PCM with OCRA controlling the counter maximum
// CS01 = clock scalar /8
// COMA = toggle on compare match (01)
TCCR0A = _BV(COM0A0) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
TCCR0B = _BV(WGM02) | _BV(CS01);
OCR0A = 255; // the compare limit (reduce this for higher frequency PWM)
// frequency = 16MHz/scalar/(OCR0A+1)
// = 16000000/8/256
// = 7812 Hz
// if we change the scalar to 1 and OCR0A to 255...
// frequency = 16000000/1/256
// = 62.5KHz
// if we change the scalar to 8 and OCR0A to 99...
// frequency = 16000000/8/100
// = 20KHz
// and note, Output A is fixed frequency - use B instead
// Output B is based on the duty cycle written to OCR0B; i.e., (OCRB+1)/(OCRA+1)%
OCR0B = 0; // start with duty 0%
// PWW is already running at this point.
// Code after here is just testing it works
// Debug
Serial.begin(9600);
while (! Serial);
Serial.println("Duty?");
}
void loop() {
// Testing - set the duty value from 0 to OCR0A
if (Serial.available()) {
int duty = Serial.parseInt();
OCR0B = duty;
Serial.print(duty);
}
}
Return to Andrew Davie's Arduino Televisor
Users browsing this forum: No registered users and 1 guest