Dynamische pulsen met Timer1
17 berichten
• Pagina 1 van 2 • 1, 2
Dynamische pulsen met Timer1
hallo,
Ben bezig met de A-Mega2560 om een pulstrein te maken die verschillende pulsbreedtes hebben (géén PWM).
Bijvoorbeeld> puls1: level=1,breedte=400µs -- puls2: level=0, breedte=900µs -- puls3: level=1, breedte=500µs -- puls4: level=0,breedte=350µs enz.
Geprobeerd met de Timer1-CTC mode: een 'gewone' pulstrein maken (van bv 400µs) is geen enkel probleem.
Echter, op het moment dat de Timer gestopt wordt om een nieuwe OCR1A waarde in te voeren gaat het fout: de single-puls wordt dan 1.049s ipv de ingestelde 400µs ... .
Gebruikte code is de sketch van: http://www.engblaze.com/microcontroller ... nterrupts/
Wat is er fout gegaan?
Alvast dank!
grtn, liemstra.
Ben bezig met de A-Mega2560 om een pulstrein te maken die verschillende pulsbreedtes hebben (géén PWM).
Bijvoorbeeld> puls1: level=1,breedte=400µs -- puls2: level=0, breedte=900µs -- puls3: level=1, breedte=500µs -- puls4: level=0,breedte=350µs enz.
Geprobeerd met de Timer1-CTC mode: een 'gewone' pulstrein maken (van bv 400µs) is geen enkel probleem.
Echter, op het moment dat de Timer gestopt wordt om een nieuwe OCR1A waarde in te voeren gaat het fout: de single-puls wordt dan 1.049s ipv de ingestelde 400µs ... .
Gebruikte code is de sketch van: http://www.engblaze.com/microcontroller ... nterrupts/
Wat is er fout gegaan?
Alvast dank!
grtn, liemstra.
Advertisement
Re: Dynamische pulsen met Timer1
Waar is het voor ? Misschien bestaat er al een library voor.
Ik begrijp niet helemaal wat je bedoelt met: level=1, level=0, level=1
Wanneer je iets wijzigt aan de frequentie of de pwm, dan wordt over het algemeen de timer opnieuw ingesteld.
Kun je jouw sketch laten zien ?
Ik begrijp niet helemaal wat je bedoelt met: level=1, level=0, level=1
Wanneer je iets wijzigt aan de frequentie of de pwm, dan wordt over het algemeen de timer opnieuw ingesteld.
Kun je jouw sketch laten zien ?
- nicoverduin
- Berichten: 5043
- Geregistreerd: 13 Mei 2013, 20:57
- Woonplaats: Heemskerk
Re: Dynamische pulsen met Timer1
Ik denk dat ie met levels bedoeld logic levels.
Re: Dynamische pulsen met Timer1
@koepel: hieronder de gebruikte sketch, rechtoe rechtaan vanaf de engblaze.com site met wat lokale aanpassingen>
// Arduino timer CTC interrupt example
// http://www.engblaze.com
// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 3
void setup()
{
pinMode(LEDPIN, OUTPUT);
Serial.begin(9600);
// initialize Timer1
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count:
OCR1A = 1;
// turn on CTC mode:
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 256 prescaler:
TCCR1B |= (1 << CS12);
// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
// enable global interrupts:
sei();
}
void loop()
{
// do some crazy stuff while my LED keeps blinking
}
ISR(TIMER1_COMPA_vect)
{
digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}
-------------------------------------------------------------
@nicoverduin: correct, met 'level' bedoelde ik idd de logic levels H en L.
--------------------------------------------------------------
Sorry voor de vaagheden. Hier wat informatie over het project:
1. Waar het voor is: het doel is om data die afkomstig is van een OpenTherm-CV ketel na te spelen op de A-Mega (tbv een andere project). Deze CV data is een zgn Manchester-codestream, waarbij de éénen en de nullen vlgs een bepaalde protocol ontstaan.
Het is dus deze datastream die ik tracht te reproduceren via een Timer procedure. Gedachte is dus: een H-puls genereren van x-µs, de daaropvolgende een L-puls van y-µs enz. enz. Het is dus géén PWM.
Idee is dan om Timer1 in de CTC modus te starten met een bepaalde countwaarde, bv "1" voor een pulsbreedte van 32µs bij een clkfreq van 16MHz en Prescaler=256.
Als je de Timer as-is laat lopen, gaat dit "treintje" perfect. Echter, doel is dan om ná de eerste puls van 32µs de Timer te stoppen en de countwaarde (OCR1A) te wijzigen in, bv"28", om een pulsbreedte te krijgen van "461µs".
Hier gaat het dus fout ... .
Gedrag is: zodra ik Timer1 stop verschijnt op de LogicAnalyzer idd slechts één puls, maar die is niet meer die van "32"µs ... maar een heel 'rare' 1.048s .... (?).
Probleem zou je dus kunnen terugbrengen tot: hoe creëer ik een gedefinieerde single-pulse? Een soort One-Shot ...
2. Er is gekeken/gewerkt met diverse Timer libraries, maar die bieden niet de 'vrijheden' die ik nodig heb voor dit Manchester-code-playback ... .
Dank voor het reageren!
grtn.
// Arduino timer CTC interrupt example
// http://www.engblaze.com
// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 3
void setup()
{
pinMode(LEDPIN, OUTPUT);
Serial.begin(9600);
// initialize Timer1
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count:
OCR1A = 1;
// turn on CTC mode:
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 256 prescaler:
TCCR1B |= (1 << CS12);
// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
// enable global interrupts:
sei();
}
void loop()
{
// do some crazy stuff while my LED keeps blinking
}
ISR(TIMER1_COMPA_vect)
{
digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}
-------------------------------------------------------------
@nicoverduin: correct, met 'level' bedoelde ik idd de logic levels H en L.
--------------------------------------------------------------
Sorry voor de vaagheden. Hier wat informatie over het project:
1. Waar het voor is: het doel is om data die afkomstig is van een OpenTherm-CV ketel na te spelen op de A-Mega (tbv een andere project). Deze CV data is een zgn Manchester-codestream, waarbij de éénen en de nullen vlgs een bepaalde protocol ontstaan.
Het is dus deze datastream die ik tracht te reproduceren via een Timer procedure. Gedachte is dus: een H-puls genereren van x-µs, de daaropvolgende een L-puls van y-µs enz. enz. Het is dus géén PWM.
Idee is dan om Timer1 in de CTC modus te starten met een bepaalde countwaarde, bv "1" voor een pulsbreedte van 32µs bij een clkfreq van 16MHz en Prescaler=256.
Als je de Timer as-is laat lopen, gaat dit "treintje" perfect. Echter, doel is dan om ná de eerste puls van 32µs de Timer te stoppen en de countwaarde (OCR1A) te wijzigen in, bv"28", om een pulsbreedte te krijgen van "461µs".
Hier gaat het dus fout ... .
Gedrag is: zodra ik Timer1 stop verschijnt op de LogicAnalyzer idd slechts één puls, maar die is niet meer die van "32"µs ... maar een heel 'rare' 1.048s .... (?).
Probleem zou je dus kunnen terugbrengen tot: hoe creëer ik een gedefinieerde single-pulse? Een soort One-Shot ...
2. Er is gekeken/gewerkt met diverse Timer libraries, maar die bieden niet de 'vrijheden' die ik nodig heb voor dit Manchester-code-playback ... .
Dank voor het reageren!
grtn.
Re: Dynamische pulsen met Timer1
een andere benadering isbijvoorbeeld een timer te zetten op bijv 100 us en dan 4 pulsen afwachten dan heb je 400 us, of iets dergelijks, dan hoef je niet moeilijk te doen met de timers.
net zoals 60 seconden is 1 minuut.
net zoals 60 seconden is 1 minuut.
paul deelen
shooter@home.nl
shooter@home.nl
Re: Dynamische pulsen met Timer1
Waar kan ik vinden hoe het OpenTherm signaal er uit ziet ?
Als het inderdaad een meervoud is van 100 µs, dan kun je doet wat shooter zegt.
Maar 100 µs is weinig, misschien heb je een snellere Arduino nodig.
Er zijn verschillende libraries die een soort van puls-trein gebruiken:
* IR libraries
* NeoPixel
* OneWire
* DHT11, DHT22
* VirtualWire/RadioHead in TX mode
Bij de NeoPixel komt het er echt op aan. In de broncode (https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp) zie je dat de interrupts uit worden gezet, en assembly code wordt gebruikt om de juiste timing te maken.
De OneWire (https://github.com/PaulStoffregen/OneWire/blob/master/OneWire.cpp) zet ook de interrupts uit en gebruikt direkt naar de registers schrijven om snel een uitgang te wijzigen, en de Arduino delayMicroseconds() functie.
Als het inderdaad een meervoud is van 100 µs, dan kun je doet wat shooter zegt.
Maar 100 µs is weinig, misschien heb je een snellere Arduino nodig.
Er zijn verschillende libraries die een soort van puls-trein gebruiken:
* IR libraries
* NeoPixel
* OneWire
* DHT11, DHT22
* VirtualWire/RadioHead in TX mode
Bij de NeoPixel komt het er echt op aan. In de broncode (https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp) zie je dat de interrupts uit worden gezet, en assembly code wordt gebruikt om de juiste timing te maken.
De OneWire (https://github.com/PaulStoffregen/OneWire/blob/master/OneWire.cpp) zet ook de interrupts uit en gebruikt direkt naar de registers schrijven om snel een uitgang te wijzigen, en de Arduino delayMicroseconds() functie.
Re: Dynamische pulsen met Timer1
@paul-shooter: dank voor je reaktie.
Idee is goed, alleen zit dan nog steeds met het basis-issue: om de volgende puls te maken moét ik de Timer stoppen alvorens de countwaarde te wijzigen. En hier gaat het dus fout ... .
Ik mis dus iets/doe iets basiek fout met een of ander register danwel procedure. Alhoewel de voorbeeldsketches allemaal iets 'simpels' zeggen:
<quote>To stop the timer you have to clear the three bits CS10, CS11 and CS12.<endquote>
of ook: <quote>TCCR1A = 0; //set entire TCCR1A (Timer/Counter Control Register) register to 0<endquote>
De Timer stopt inderdaad ... maar de gemaakte puls heeft dan een constante waarde van 1.049s - vandaar m'n vermoeden dat ik iets onrechtmatigs doe.
grtn.
Idee is goed, alleen zit dan nog steeds met het basis-issue: om de volgende puls te maken moét ik de Timer stoppen alvorens de countwaarde te wijzigen. En hier gaat het dus fout ... .
Ik mis dus iets/doe iets basiek fout met een of ander register danwel procedure. Alhoewel de voorbeeldsketches allemaal iets 'simpels' zeggen:
<quote>To stop the timer you have to clear the three bits CS10, CS11 and CS12.<endquote>
of ook: <quote>TCCR1A = 0; //set entire TCCR1A (Timer/Counter Control Register) register to 0<endquote>
De Timer stopt inderdaad ... maar de gemaakte puls heeft dan een constante waarde van 1.049s - vandaar m'n vermoeden dat ik iets onrechtmatigs doe.
grtn.
Re: Dynamische pulsen met Timer1
@koepel:
Hierbij een link waar de Manchester code uitgelegd wordt:
https://en.wikipedia.org/wiki/Manchester_code
De data is dus niet een veelvoud van 100µs, maar kan variëren van 400µs tot 500ms ... . De 'lange' tijden zijn dan wachttijden in de 'conversatie' tussen zender (CV ketel) en ontvanger (CV regelaar).
Dank voor de tips + url's! Zal er naar gaan kijken.
Voor nu ... paar uurtjes op één oor liggen
grtn.
Hierbij een link waar de Manchester code uitgelegd wordt:
https://en.wikipedia.org/wiki/Manchester_code
De data is dus niet een veelvoud van 100µs, maar kan variëren van 400µs tot 500ms ... . De 'lange' tijden zijn dan wachttijden in de 'conversatie' tussen zender (CV ketel) en ontvanger (CV regelaar).
Dank voor de tips + url's! Zal er naar gaan kijken.
Voor nu ... paar uurtjes op één oor liggen
grtn.
Re: Dynamische pulsen met Timer1
Uhm... de bedoeling van dit forum is dat jij laat zien wat niet werkt, en hopelijk kunnen we er dan iets van zeggen of alternatieven aanbrengen.
Kun je misschien de sketch laten zien die het niet doet ? Dan kunnen we dat eventueel zelf proberen. Die sketch die je liet zien laat een ledje knipperen.
Staat ergens beschreven hoe het OpenTherm signaal er precies uit ziet ? Ik weet wat manchester code is.
In plaats van wekenlang (maandenlang) te tobben, zou je kunnen beginnen met iets dat schijnt te werken: https://github.com/amvv/ArduinoOpenTherm.
De OT_encoder werkt met een vaste timer interrupt zoals shooter schreef. Het is een paar jaar oud, dus ik vermoed dat de code bedoeld is voor de Arduino Uno.
In het voorbeeld zie je hoe verschillende waarden kunnen worden gebruikt (MM1, MM2, MM3, MM4).
Ik wilde PulseView + sigrok eens proberen. Dat valt een beetje tegen Misschien heb ik nog een oudere versie
Test met Arduino Uno en OT_encoder sketch.
Een pin toggle in de interrupt deed ik door pin 13 als output te zetten en in de interrupt een "PINB = bit(5);". Er is een interrupt iedere 512 µs.
Het donkere plaatje is salaea, die kan zelfs Manchester code decoderen.
Kun je misschien de sketch laten zien die het niet doet ? Dan kunnen we dat eventueel zelf proberen. Die sketch die je liet zien laat een ledje knipperen.
Staat ergens beschreven hoe het OpenTherm signaal er precies uit ziet ? Ik weet wat manchester code is.
In plaats van wekenlang (maandenlang) te tobben, zou je kunnen beginnen met iets dat schijnt te werken: https://github.com/amvv/ArduinoOpenTherm.
De OT_encoder werkt met een vaste timer interrupt zoals shooter schreef. Het is een paar jaar oud, dus ik vermoed dat de code bedoeld is voor de Arduino Uno.
In het voorbeeld zie je hoe verschillende waarden kunnen worden gebruikt (MM1, MM2, MM3, MM4).
Ik wilde PulseView + sigrok eens proberen. Dat valt een beetje tegen Misschien heb ik nog een oudere versie
Test met Arduino Uno en OT_encoder sketch.
Een pin toggle in de interrupt deed ik door pin 13 als output te zetten en in de interrupt een "PINB = bit(5);". Er is een interrupt iedere 512 µs.
Het donkere plaatje is salaea, die kan zelfs Manchester code decoderen.
- Bijlagen
-
- Output signaal met pin toggle in interrupt.
- toggle.png (6.36 KiB) 10531 keer bekeken
-
- Saleae capture met manchester decodering.
- saleae.png (9.62 KiB) 10532 keer bekeken
-
- PulseView + Sigrok
- sigrok.png (16.96 KiB) 10532 keer bekeken
Re: Dynamische pulsen met Timer1
@koepel:
Mijn excuses ... de manier waarop ik het probleem tracht te schetsen is ietwat 'warrig' ... . Ik geef hieronder nogwel een link naar de omschrijving van het OT protocol: <https://nl.wikipedia.org/wiki/OpenTherm>.
Tegelijkertijd wil ik het daarbij laten - inclusief het Manchester topic. Is op dit moment irrelevant voor mij.
Terug naar je commentaar: hieronder tref je de volledige sketch die ik momenteel gebruik om het probleem duidelijk te maken (is een paar berichten eerder ook al gepubliceerd). Nu met detail toelichting:
- sketch overgenomen van: //http://www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts/
--------------------------------------------------------------------------------------
// Arduino timer CTC interrupt example
// http://www.engblaze.com
// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 3
void setup()
{
pinMode(LEDPIN, OUTPUT);
Serial.begin(9600);
// initialize Timer1
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count:
OCR1A = 1;
// turn on CTC mode:
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 256 prescaler:
//TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
// enable global interrupts:
sei();
}
void loop()
{
// do some crazy stuff while my LED keeps blinking
}
ISR(TIMER1_COMPA_vect)
{
digitalWrite(LEDPIN, !digitalRead(LEDPIN));
cli(); // disable global interrupts
//TCCR1B &= ~(1 << CS10 | 1 << CS11 | 1 << CS12); //stop the Timer (clear bits C10,11,12)
//TCCR1A = 0; // set entire TCCR1A register to 0
//TCCR1B = 0; // same for TCCR1B
}
--------------------------------------------------------------------------------------
- negeer commentaar in de (lege-) void loop.
- Saleae capture op Arduino pin 3 én code 'as-is' geeft een correcte pulstrein van 32µs. Zie plaatje hieronder:
Hier is duidelijk te zien dat de gecalculeerde 32µs puls (OCR1A=1, f=16MHz, Prescale=256) ook tevoorschijn komt.
Het probleem doet zich voor wanneer de Timer gestopt wordt in de CompareMatch sectie: code <TCCR1B &= ~(1 << CS10 | 1 << CS11 | 1 << CS12); //stop the Timer (clear bits C10,11,12)> speelt dan mee. De puls ziet er nu opeens alsvolgt uit:
De '32µs' puls is nu '1.049s' geworden .... (!).
Dít is dus (op dit moment) mijn probleem. (skip alle OpenTherm en Manchester texten, nu niet relevant).
Ik doe iets principieels fout ... .
grtn, L.
Mijn excuses ... de manier waarop ik het probleem tracht te schetsen is ietwat 'warrig' ... . Ik geef hieronder nogwel een link naar de omschrijving van het OT protocol: <https://nl.wikipedia.org/wiki/OpenTherm>.
Tegelijkertijd wil ik het daarbij laten - inclusief het Manchester topic. Is op dit moment irrelevant voor mij.
Terug naar je commentaar: hieronder tref je de volledige sketch die ik momenteel gebruik om het probleem duidelijk te maken (is een paar berichten eerder ook al gepubliceerd). Nu met detail toelichting:
- sketch overgenomen van: //http://www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts/
--------------------------------------------------------------------------------------
// Arduino timer CTC interrupt example
// http://www.engblaze.com
// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 3
void setup()
{
pinMode(LEDPIN, OUTPUT);
Serial.begin(9600);
// initialize Timer1
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count:
OCR1A = 1;
// turn on CTC mode:
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 256 prescaler:
//TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
// enable global interrupts:
sei();
}
void loop()
{
// do some crazy stuff while my LED keeps blinking
}
ISR(TIMER1_COMPA_vect)
{
digitalWrite(LEDPIN, !digitalRead(LEDPIN));
cli(); // disable global interrupts
//TCCR1B &= ~(1 << CS10 | 1 << CS11 | 1 << CS12); //stop the Timer (clear bits C10,11,12)
//TCCR1A = 0; // set entire TCCR1A register to 0
//TCCR1B = 0; // same for TCCR1B
}
--------------------------------------------------------------------------------------
- negeer commentaar in de (lege-) void loop.
- Saleae capture op Arduino pin 3 én code 'as-is' geeft een correcte pulstrein van 32µs. Zie plaatje hieronder:
Hier is duidelijk te zien dat de gecalculeerde 32µs puls (OCR1A=1, f=16MHz, Prescale=256) ook tevoorschijn komt.
Het probleem doet zich voor wanneer de Timer gestopt wordt in de CompareMatch sectie: code <TCCR1B &= ~(1 << CS10 | 1 << CS11 | 1 << CS12); //stop the Timer (clear bits C10,11,12)> speelt dan mee. De puls ziet er nu opeens alsvolgt uit:
De '32µs' puls is nu '1.049s' geworden .... (!).
Dít is dus (op dit moment) mijn probleem. (skip alle OpenTherm en Manchester texten, nu niet relevant).
Ik doe iets principieels fout ... .
grtn, L.
17 berichten
• Pagina 1 van 2 • 1, 2
Wie is er online?
Gebruikers in dit forum: Geen geregistreerde gebruikers en 5 gasten