brzdové svetlo na RC auto cez Atmega8

Podle mne by to mělo fungovat takto, ale nezkoušel jsem to v reálu.

[code]//osc. = 8 MHz
#include <mega8.h>
#include <delay.h>

#define LED1 PORTC.5 // LED na porte C5 a C4
#define LED2 PORTC.4
#define SIGNAL PIND.2 // riadiaci signál z prijímača - vstup

volatile unsigned char Servo;
volatile unsigned char off;

//--------------------------------------------------------------------
interrupt [EXT_INT0] void ext_int0_isr(void) // Externé prerušenie 0
{
if (SIGNAL) // L-H interrupt
TCNT0 = 0; // vynulovanie časovača 0
else // H-L interrupt
Servo = TCNT0; // Servo = hodnota časovača (délka kladného pulsu)
}

//--------------------------------------------------------------------
// Timer0 přeteče za 32 ms (musí být delší než perioda signálu)
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
off = 1;
}

//=====================================================================
void main(void)
{

PORTC = 0x00;      // PC0 az PC5 = výstup
DDRC  = 0b00111111;
TIMSK = 0x01;      // povolenie prerušenia Timer0 overflow
TCCR0 = 5;         // start timer0, presc 1024

GICR  = (1<<6);    // External Interrupt0 enable
MCUCR = (1<<2);    // INT0 Mode: Any change

//test HW
PORTC = 255;       //LED ON
delay_ms(100);
PORTC = 0;         //LED OFF
//koniec testu

#asm("sei")

while (1)          // nekonečná slučka
{   
     if(off)       // no signal
     {
         off  = 0;
         LED2 = 1;
     }
     else 
     {    
        if(Servo > 12) {LED1=1;} // puls > 1.5 ms  
        else           {LED1=0;} // puls < 1.5 ms
        LED2 = 0;
     }
} 

}[/code]

Vyskúšal som ten program ale tiež nefunguje, resp. popíšem.
Po zapnutí napájania prebehne test HW a po ňom sa rozsvieti LED1 (jemne preblikáva - takmer nepozorovane) k pretečeniu off=1 nedôjde.
Pri zapnutí napájania s riadiacim kanálom to isté ale na pohyb páky LED1 reaguje jemným stlmením svietivosti ale nelineárne (počas pohybu niekoľko krát jemne stlmí a rozsvieti)
Skúsim sa s tým ešte pohrať, možno som nejakú malú chybu prehliadol. Ak prídem nato kde je chyba dám vedieť.

Tak jsem to vyzkoušel na desce a opravil.

[code]//osc. = 8 MHz
#include <mega8.h>
#include <delay.h>

#define LED1 PORTC.5 // LED na porte C5 a C4
#define LED2 PORTC.4
#define SIGNAL PIND.2 // riadiaci signál z prijímača - vstup

volatile unsigned char Servo, zadny_signal;

//--------------------------------------------------------------------
interrupt [EXT_INT0] void ext_int0_isr(void) // Externé prerušenie 0
{
if (SIGNAL) // L-H interrupt
TCNT0 = 0; // vynulovanie časovača 0
else // H-L interrupt
Servo = TCNT0; // Servo = hodnota časovača (délka kladného pulsu)
zadny_signal = 0;
}

//--------------------------------------------------------------------
// Timer0 přeteče za 32 ms (musí být delší než perioda signálu)
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
zadny_signal = 1;
}

//=====================================================================
void main(void)
{

PORTC = 0;         // PC0 az PC5 = výstup
DDRC  = 0b00111111;

TIMSK = 0x01;      // povolenie prerušenia Timer0 overflow
TCCR0 = 5;         // start timer0, presc 1024

GICR  = (1<<6);    // External Interrupt0 enable
MCUCR = 1;         // INT0 Mode: Any change

//test HW
PORTC = 255;       //LED ON
delay_ms(100);
PORTC = 0;         //LED OFF
//koniec testu

#asm("sei")

while (1)          // nekonečná slučka
{   
     if(zadny_signal)   
     {
         LED2 = 1;
     }
     else
     {   
         if(Servo > 12)  {LED1=1;} // puls > 1.5 ms 
         else            {LED1=0;} // puls < 1.5 ms
         LED2 = 0;
     }
}

}
[/code]

Ste to skúšal aj s modelárskym prijímačom či len na sucho na plošáku?

Ja som to vyskúšal. Pretečenie funguje spoľahlivo. Ale LED 1 na pohyb riadiacej páky neregovalo (ani sa nerozsvietilo) Začalo reagovať až keď som doplnil ( PORTD=0x00; DDRD=0x03;) a zmenil podmienku z 12 na 1

 if(Servo > 1) {LED1=1;}
  else             {LED1=0;}

V tomto prípade začal reagovať od zhasnutej led. S pridávaním na páke začala led1 lineárne blikať od pomala až do rýchla (úplne svieť nesvieti, len veľmi rýchlo blika)
Problém je v tom že potrebujem aby LED reagovala skokovo. Napr.: v 50% páky sa rozsvieti a pod zhasne.

A teraz sa spýtam možno hlúpu otázku, ale nerozumiem prečo v teste ste dali PORTC=255?
Myslel som že stačí zadať 0 pre log0 a 1 pre log1 na výstupe.

vstupny register DDRD by mal byt asi DDRD = 0x04, aby to zodpovedalo PIND.2
EDIT: hlupost. pomylil som sa.

Udělal jsem si z druhého mproc zdroj impulsů 1 ms a 2 ms. Mezera 18 ms.
Ledka spolehlivě přepíná.

Při impulsu 1 ms je hodnota proměnné “Servo” 8, při impulsu 2 ms 16.
Takže rozhodovací hodnota 12 je správná, odpovídá středu páky.
Máš nastavený oscilátor 8 MHz?

Abych ušetřil dva řádky kódu.
PORTC = 255 je totéž jako PORTC = 0b11111111.

A k tomu tě vedla jaká úvaha?
Na vstupu (Portd.2) se tím nic nezmění.

Oscilátor som nastavil v CV ( Projekt/configure/c compiler/clock 8MHz) teda aspoň tak viem že sa nastavuje.
K tomu PortD, máš pravdu vlastne sa nič nemení len som ho zadefinoval a určil som že PD0 a PD1 sú vystupy (zas na iné led)
Problém je že mi to nefunguje :frowning:
Možno je problém v tom že impul je síce 1 až 2ms ale medzera by sa mala pohybovať od 10 do 15 ms podľa toho ako to rozdelí prijímač. Faktom zostáva že na reál prijímači to nejde :frowning:

V CV se nastavuje skutečný kmitočet oscilátoru v mikroprocesoru.
Ten je z továrny nastavený na 1 MHz.
Měnil jsi ho na 8MHz?
Typoval bych že ne.

PS
Délka mezery tady nemá vliv.

Menil som ho len tam ako som napísal, neviem ako inak sa dá meniť kmitočet oscilátora. Prikladám foto s mojimi nastaveniami.

Frekvence se mění pomocí fuses (zprostředkovává programátor). To, co jsi nastavil je pouze informace pro překladač aby fungovaly funkce delay. S reálnou frekvencí nemá nic společného.

Som si myslel, že sa to robí tým. Keďže to neviem tak sa račej spýtam aby som niečo nepokazil.
Ako sa mení kmitočet oscilátora?
Stačí zadať do kódu #define F_CPU 8000000UL
alebo ako?

Inak AB mám ešte otázku: deličku si nastavil na 1024 čiže TCCR0 = 5;
ale v pretečení udávaš že pretečie za 32ms. Ale ak sa nemílim tak pre 1024 zodpovedá 128ms a 32 ms zodpovedá pre deličku 256 čiže TCCR =4;
Ak sa mýlim tak sorry.

Takže tvůj procesor běží na frekvenci 1 MHz.
To nejde změnit žádným zápisem v kódu ani nastavením v CV.
Kmitočet oscilátoru se dá změnit pouze pomocí programátoru, změnou fuse bitů (konfiguračních bitů).
Postup nastavení se liší podle typu použitého programátoru.
Je to ale choulostivá operace a při nesprávném nastavení může čip přestat komunikovat s programátorem.

Doporučuji nechat oscilátor jak je a v CV nastavit správně “clock: 1MHz”.
Posílám program upravený pro 1 MHz.
Při správném nastavení se po resetu Ledky rozsvítí na 1 vteřinu.

Čas přetečení se počítá takto:
čas[ms] = počet_kroků_čítače * předdělič / F_CPU[kHz]

Čítač0 přeteče po 256 krocích a F_CPU byl podle tebe 8 MHz.
čas = 256 * 1024 / 8000 = 32,768 ms
test1.c (1.74 KB)

Už to funguje, ďakujem Vám veľmi pekne, hlavne tebe AB veľmi ste mi pomohli a hlavne veľa naučili. Lebo som pracoval s mylnými informáciami…

Hah… mám pocit, že všetko o čo sa snažím mi nefunguje. Snažím sa teraz urobiť ešte jeden riadený kanál, spravil som upravenú kópiu predošlého kódu, povolil som prerušenie na int1 aj spustenie a nastavenie časovača 1B. Funguje mi riadenie cez Servo a Servo2 ale pretečenie mi na druhom nefunguje (Ziadny_signal_2). prikladám kód:

[code]
//osc. = 1 MHz
#include <mega8.h>
#include <delay.h>

#define LED1 PORTC.5 // LED1 až LED6 spína LED cez GND
#define LED2 PORTC.4
#define LED3 PORTC.3
#define LED4 PORTC.2

#define SIGNAL PIND.2 // riadiaci signál z prijímača - vstup
#define SIGNAL2 PIND.3 // riadiaci signál2 z prijímača - vstup

volatile unsigned char Servo, Servo2, Ziadny_signal, Ziadny_signal_2;

//--------------------------------------------------------------------
interrupt [EXT_INT0] void ext_int0_isr(void) // Externé prerušenie 0
{
if (SIGNAL) // L-H interrupt
TCNT0 = 0; // vynulovanie časovača 0
else // H-L interrupt
Servo = (TCNT0*10); // Servo = hodnota časovača (délka kladného pulsu) *10 (kvôli presnejšiemu nastavniu rozsahu)
Ziadny_signal = 0;
}

interrupt [EXT_INT1] void ext_int1_isr(void) // Externé prerušenie 1
{
if (SIGNAL2) // L-H interrupt
TCNT1 = 0; // vynulovanie časovača 1
else // H-L interrupt
Servo2 = (TCNT1*10); // Servo2 = hodnota časovača (délka kladného pulsu) *10 (kvôli presnejšiemu nastavniu rozsahu)
Ziadny_signal_2 = 0;
}
//--------------------------------------------------------------------

// Timer0 přeteče za 64 ms (musí být delší než perioda signálu)
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
Ziadny_signal = 1;

}

// Timer0 přeteče za 64 ms (musí být delší než perioda signálu)
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
Ziadny_signal_2 = 1;

}

//=====================================================================
void main(void)
{
PORTB = 0x07; //port B0, B1 a B2 je vstup s pullup rezistorom
DDRB = 0x00;

PORTC = 0x00;      // PC0 az PC5 = výstup
DDRC  = 0x3F;

PORTD = 0x00;      // PD0 az PD1 = výstup     // PD2 az PD3 =vstup 
DDRD  = 0x03;

TIMSK = 0x05;      // povolenie prerušenia overflow Timer0 a Timer1
TIFR  = 0x05;      // overflow flag enabled Timer0 a Timer1
TCCR0 = 4;         // start timer0, presc 256             
TCCR1B= 4;         // start timer1B, presc 256  

GICR  = 0xC2;      // External Interrupt0 a 1 enable
MCUCR = 5;         // INT0 a INT 1 Mode: Any change   


//test HW
PORTC = 255;       //LED ON
delay_ms(1000);
PORTC = 0;         //LED OFF
delay_ms(1000);
//koniec testu

#asm("sei")

while (1)          // nekonečná slučka
{   
     
     if(Ziadny_signal_2)   
     {
         LED4 = 1;
         LED3 = 0;
     }
     else
     {   
         if(Servo2 > 50){LED3=1;} // puls > 1.5 ms     //1ms=39  , 1,5ms=58   ,2ms=78
         else           {LED3=0;} // puls < 1.5 ms
         LED4 = 0;
     }
     
     if(Ziadny_signal)   
     {
         LED2 = 1;
         LED1 = 0;

     }
     else
     {   
         if(Servo > 50) {LED1=1;} // puls > 1.5 ms     //1ms=39  , 1,5ms=58   ,2ms=78
         else           {LED1=0;}     // puls < 1.5 ms
         LED2 = 0;   
         
         
     }
}

}[/code]

Kto vie prečo?

Timer1 je šestnáctibitový. Počítá od 0 do 65535.
A výpadek signálu stačí sledovat v jednom kanálu, ne?

no stačilo by, ale chcel som sa poistiť že keď druhý nezapojím tak to aj tak bude fungovať.

Ale práve to že timer1 je 16bitový som nevedel, Zmenil som predeličku na 1 a prerátal počet tikov na 1,5ms a už to ide aj pretečenie funguje.
Ďakujem za radu.