Programovatelný impulsní generátor
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Programovatelný impulsní generátor
Zdravím všechny,
jsem začátečník s humanitárním vzděláním, zde nový, žádný profík, ryzí amatér.
S Arduinem se teprve učím. Umím nějaké blikání, pískání a drobnosti z knih, zvládnu implementaci a mini-úpravy jiných programů.
Nyní mi však vyvstal problém - potřebuji testovat driver DC motoru a motory k němu připojené na dost parametrů.
K tomu potřebuji generátor pulsů (obdélník) u kterého by šlo nastavit kmitočet (stačí střída 1:3-5) od cca 10imp/sec do 750 000imp sec.
To ale není vše, dále je potřeba počítat počet impulsů a vysílat je na pin jen do předem nastaveného počtu (příkladně 1 250 557) a to
jak výše uvedeno, nastavenou rychlostí impulsů. To s možností opakovat to, ale i měnit.
Představa ovládání je otočný enkodér a pár tlačítek, zobrazení dislplay 4 řádky nebo grafika.
Jak jsem výše uvedl neumín to naprogramovat a tak hledám někoho kdo by to udělal sám nebo mi pomohl to vytvořit (samozřejmě i za úplatu)
Problém je v tom, že to musí být vytvořeno v historicky přijatelné době. Mechanicky Arduino, periferie i krabičku si udělám. Jde mi jen o sw.
Pro případného zájemce o spolupráci bych měl i další téma k pokračování spolupráce - nositelná elektronika s Arduinem.
Protože nevím ani jak začít, uvítám každý podnět.
jsem začátečník s humanitárním vzděláním, zde nový, žádný profík, ryzí amatér.
S Arduinem se teprve učím. Umím nějaké blikání, pískání a drobnosti z knih, zvládnu implementaci a mini-úpravy jiných programů.
Nyní mi však vyvstal problém - potřebuji testovat driver DC motoru a motory k němu připojené na dost parametrů.
K tomu potřebuji generátor pulsů (obdélník) u kterého by šlo nastavit kmitočet (stačí střída 1:3-5) od cca 10imp/sec do 750 000imp sec.
To ale není vše, dále je potřeba počítat počet impulsů a vysílat je na pin jen do předem nastaveného počtu (příkladně 1 250 557) a to
jak výše uvedeno, nastavenou rychlostí impulsů. To s možností opakovat to, ale i měnit.
Představa ovládání je otočný enkodér a pár tlačítek, zobrazení dislplay 4 řádky nebo grafika.
Jak jsem výše uvedl neumín to naprogramovat a tak hledám někoho kdo by to udělal sám nebo mi pomohl to vytvořit (samozřejmě i za úplatu)
Problém je v tom, že to musí být vytvořeno v historicky přijatelné době. Mechanicky Arduino, periferie i krabičku si udělám. Jde mi jen o sw.
Pro případného zájemce o spolupráci bych měl i další téma k pokračování spolupráce - nositelná elektronika s Arduinem.
Protože nevím ani jak začít, uvítám každý podnět.
Re: Programovatelný impulsní generátor
Já myslím, že to jen s Arduinem nepůjde.
Generování frekvence 750kHz a ještě k tomu nastavování střídy (až 1:5) a zároveň počítání impulzů se podle mého názoru s procesorem, který běží na 16MHz, nedá nezvládout.
Zkusil jsem ten nejjednodušší a nejrychlejší kód:
A pak jsem měřil frekvenci na výstupu D13. Naměřil jsem jen nějakých 145kHz.
Když jsem do toho doplnil ještě střídu 1:5, klesla frekvence na pouhých 22kHz
Možná že to někdo dokáže napsat v assembleru, čímž by se rychlost asi zvýšila, ale to já nedokážu.
Spíš bych to viděl na nějaký externí generátor (napřiklad AD9833), který by se řídil komunikací pomocí Arduina.
Přílohy výstupů z ukázkových programů:
Generování frekvence 750kHz a ještě k tomu nastavování střídy (až 1:5) a zároveň počítání impulzů se podle mého názoru s procesorem, který běží na 16MHz, nedá nezvládout.
Zkusil jsem ten nejjednodušší a nejrychlejší kód:
Kód: Vybrat vše
void setup(void)
{
pinMode(13,OUTPUT);
}
void loop(void)
{
digitalWrite(13,HIGH);
digitalWrite(13,LOW);
}
A pak jsem měřil frekvenci na výstupu D13. Naměřil jsem jen nějakých 145kHz.
Když jsem do toho doplnil ještě střídu 1:5, klesla frekvence na pouhých 22kHz
Kód: Vybrat vše
byte pwm;
void setup(void)
{
pinMode(13,OUTPUT);
}
void loop(void)
{
pwm ++;
if (pwm % 5 == 0) digitalWrite(13,LOW);
else digitalWrite(13,HIGH);
}
Možná že to někdo dokáže napsat v assembleru, čímž by se rychlost asi zvýšila, ale to já nedokážu.
Spíš bych to viděl na nějaký externí generátor (napřiklad AD9833), který by se řídil komunikací pomocí Arduina.
Přílohy výstupů z ukázkových programů:
Re: Programovatelný impulsní generátor
Dík za zájem a za pomoc při hledání cesty. Asi máš pravdu.Nicméně tu cestu bych rád našel.
Předpokládám, že s Mega 256 by to vyšlo asi nastejno.
Tak jsem se snažil minimalizovat požadavky a stačila by tomu pevná střída 1:1 a jako optimum do cca 600kHz.
Tak byl to už snad něco dokázalo - ale se zobrazením, cca kolik kHz?
Jinak na Arduinu netrvám, jen ten generátor co umí dát přesný počet pulsů značnou rychlostí dost potřebuji.
Jo a mám k dispozici Rabsperry Pi s displayem (touch) - ale tam jsem úplně mimoň.
Díky.
Předpokládám, že s Mega 256 by to vyšlo asi nastejno.
Tak jsem se snažil minimalizovat požadavky a stačila by tomu pevná střída 1:1 a jako optimum do cca 600kHz.
Tak byl to už snad něco dokázalo - ale se zobrazením, cca kolik kHz?
Jinak na Arduinu netrvám, jen ten generátor co umí dát přesný počet pulsů značnou rychlostí dost potřebuji.
Jo a mám k dispozici Rabsperry Pi s displayem (touch) - ale tam jsem úplně mimoň.
Díky.
Re: Programovatelný impulsní generátor
Možná by se to dalo udělat přenastavením časovačů. Tohle by mělo dát až 4MHz,ale střídu jen 0%-33%-66% Nicméně nejspíš nebude možné používat časování millis() a všechny z toho odvozené knihovny.
Kód: Vybrat vše
#include <TimerHelpers.h>
// Timer 0
// output OC0B pin 11 (D5)
const byte timer0OutputB = 5;
void setup() {
pinMode (timer0OutputB, OUTPUT);
TIMSK0 = 0; // no interrupts
Timer0::setMode (7, Timer0::PRESCALE_1, Timer0::CLEAR_B_ON_COMPARE);
OCR0A = 3; // count to 4, zero-relative
OCR0B = 1; // duty cycle
} // end of setup
void loop() {}
Re: Programovatelný impulsní generátor
Opět dík, vyzkouším. I to by mohla být cestička.
Ale až v úterý, zítra mám "Perný den".
Ale až v úterý, zítra mám "Perný den".
Re: Programovatelný impulsní generátor
Zkus knihovnu FastWrite, bude to trochu rychlejší:
#include <digitalWriteFast.h>
#define pinNum 12
//int pinNum = 9; //do not use variables, macro will revert to the slower digitalWrite()
//const int pinNum = 9; //this is a constant, will use port manipulation (fast)
void setup() {
pinModeFast(pinNum, OUTPUT);
}
void loop() {
//the pin is toggled multiple time before looping is because it took too long that the pin stayed low for 600ns, while clearing or setting the pin only took 125ns. For 16MHz Arduino Uno.
digitalWriteFast(pinNum, HIGH);
//delay(1);
digitalWriteFast(pinNum, LOW);
//delay(1);
}
----------
A nejrychlejší bitWrite:
void setup() {
pinMode(10, OUTPUT);
bitWrite(DDRB,4, 1);
}
void loop() {
bitWrite(PORTB, 4, 0);
asm volatile("nop");
bitWrite(PORTB, 4, 1);
asm volatile("nop");
}
Potom z toho 2MHz dostaneš:
http://xanadu.khnet.info/oscillo/fw_5k6_1.png
(nevím proč, ale nejde mi sem vložit obrázek)
#include <digitalWriteFast.h>
#define pinNum 12
//int pinNum = 9; //do not use variables, macro will revert to the slower digitalWrite()
//const int pinNum = 9; //this is a constant, will use port manipulation (fast)
void setup() {
pinModeFast(pinNum, OUTPUT);
}
void loop() {
//the pin is toggled multiple time before looping is because it took too long that the pin stayed low for 600ns, while clearing or setting the pin only took 125ns. For 16MHz Arduino Uno.
digitalWriteFast(pinNum, HIGH);
//delay(1);
digitalWriteFast(pinNum, LOW);
//delay(1);
}
----------
A nejrychlejší bitWrite:
void setup() {
pinMode(10, OUTPUT);
bitWrite(DDRB,4, 1);
}
void loop() {
bitWrite(PORTB, 4, 0);
asm volatile("nop");
bitWrite(PORTB, 4, 1);
asm volatile("nop");
}
Potom z toho 2MHz dostaneš:
http://xanadu.khnet.info/oscillo/fw_5k6_1.png
(nevím proč, ale nejde mi sem vložit obrázek)
Re: Programovatelný impulsní generátor
Afilip: Perfektní nápad s tím rychlým nastavováním stavu pinu pomocí registru.
Rozšířil jsem to ještě trochu o to počítání impulzů a nastavení různých frekvencí.
Přesná frekvence se už dost těžko dolaďuje, takže při nejvyšší rychlosti mám 762kHz.
Minimum je 30Hz. Pro ještě nižší frekvence by bylo nutné udělat ještě jeden podprogram a místo delayMicroseconds() tam použít obyčené delay() - pak už by tam ty "NOPy" nehrály žádnou roli.
Spouštění sekvence pomocí tlačítka na D11.
Rozšířil jsem to ještě trochu o to počítání impulzů a nastavení různých frekvencí.
Přesná frekvence se už dost těžko dolaďuje, takže při nejvyšší rychlosti mám 762kHz.
Minimum je 30Hz. Pro ještě nižší frekvence by bylo nutné udělat ještě jeden podprogram a místo delayMicroseconds() tam použít obyčené delay() - pak už by tam ty "NOPy" nehrály žádnou roli.
Spouštění sekvence pomocí tlačítka na D11.
Kód: Vybrat vše
void setup(void)
{
pinMode (5, OUTPUT); // pin D5 je vystup
pinMode (11,INPUT_PULLUP); // pin D11 je spousteci tlacitko proti GND
}
void loop(void)
{
if (digitalRead(11) == LOW) spust_generovani(1250557ul,1); // po stisku tlacitka spusti generovani impulzu
while (digitalRead(11) == LOW) {} // cekani na uvolneni spousteciho tlacitka
}
//--------------------------------------------------------------------------------
// generovani zadaneho poctu impulzu zvolenou rychlosti
// rychlost = 1 .... 762kHz (maximum)
// rychlost = 2 .... 355kHz
// rychlost = 3 .... 209kHz
// rychlost = 10 .... 53kHz
// rychlost = 20 .... 26kHz
// rychlost = 100 .... 5kHz
// rychlost = 1000 .... 500Hz
// rychlost = 10000 .... 50Hz
// rychlost = 16383 .... 30Hz (minimum)
void spust_generovani(unsigned long pocet_impulzu, unsigned int rychlost)
{
while(true)
{
pocet_impulzu --;
PORTD = PORTD & 0b11011111; // D5 na LOW - ostatni piny zustavaji
delayMicroseconds(rychlost); // doladeni na frekvenci 762Khz a stridu zhruba 1:1 (pri rychlost = 1)
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
if (pocet_impulzu == 0) return; // odpocet impulzu dosel do 0 .... ukonci generovani
PORTD = PORTD | 0b00100000; // D5 na HIGH - ostatni piny zustavaji
delayMicroseconds(rychlost); // doladeni na frekvenci 762Khz a stridu zhruba 1:1 (pri rychlost = 1)
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
}
}
//--------------------------------------------------------------------------------
Re: Programovatelný impulsní generátor
Já jsem to potřeboval doladit na přesnou frekvenci, takže jsem tam měl těch NOPů asi 40 + 40 za sebou. Jinak to doladit nešlo jakákoliv instrukce typu delay nebo millis to rozhodila naprosto nepředvídatelně.
Kdo je online
Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 13 hostů