Programovatelný impulsní generátor

Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Odpovědět
Ferrit
Příspěvky: 6
Registrován: 05 srp 2018, 10:11
Reputation: 0

Programovatelný impulsní generátor

Příspěvek od Ferrit » 05 srp 2018, 10:44

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.

AstroMiK
Příspěvky: 592
Registrován: 08 pro 2017, 19:05
Reputation: 0

Re: Programovatelný impulsní generátor

Příspěvek od AstroMiK » 05 srp 2018, 13:56

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:

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ů:
max_frq.gif
max_frq-pwm.gif

Ferrit
Příspěvky: 6
Registrován: 05 srp 2018, 10:11
Reputation: 0

Re: Programovatelný impulsní generátor

Příspěvek od Ferrit » 05 srp 2018, 16:05

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.

rejze69
Příspěvky: 174
Registrován: 02 dub 2018, 18:56
Reputation: 0

Re: Programovatelný impulsní generátor

Příspěvek od rejze69 » 05 srp 2018, 16:10

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() {}

Ferrit
Příspěvky: 6
Registrován: 05 srp 2018, 10:11
Reputation: 0

Re: Programovatelný impulsní generátor

Příspěvek od Ferrit » 05 srp 2018, 22:43

Opět dík, vyzkouším. I to by mohla být cestička.
Ale až v úterý, zítra mám "Perný den".

afilip
Příspěvky: 116
Registrován: 26 črc 2017, 16:34
Reputation: 0
Kontaktovat uživatele:

Re: Programovatelný impulsní generátor

Příspěvek od afilip » 06 srp 2018, 19:43

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)

AstroMiK
Příspěvky: 592
Registrován: 08 pro 2017, 19:05
Reputation: 0

Re: Programovatelný impulsní generátor

Příspěvek od AstroMiK » 07 srp 2018, 00:18

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.

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");
      }
  }
//--------------------------------------------------------------------------------

gen-portb.gif

afilip
Příspěvky: 116
Registrován: 26 črc 2017, 16:34
Reputation: 0
Kontaktovat uživatele:

Re: Programovatelný impulsní generátor

Příspěvek od afilip » 09 srp 2018, 16:35

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 :D jakákoliv instrukce typu delay nebo millis to rozhodila naprosto nepředvídatelně.

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 13 hostů