Čtení signálu teploměru SMT160-30-92

Zdravím, programuji teplotní čidlo SMT160. Jako mikročip jsem zvolil AMTEGA16 a nastavil interní krystal na 1000000MHz v Makefilu. Output je vyveden na pin PD3(INT1). Zatím jen kontroluji jak dlouho je signál v 1 a v 0. Všechno se mi ale zapisuje jen do proměnné signal_nula, jejíž hodnota na display skáče od 121 do 163 zhruba a proměnnná signal_jednicka je pořád nula. Prosím o radu. Je to můj první program s čtením signálu. Díky moc za pomoc :wink:

[code]
#include<avr/io.h>
#include<lcd_lib.c>
#include<util/delay.h>
#include<stdlib.h>
#include <stdio.h>
#include<avr/interrupt.h>

float teplota;
unsigned int signal_nula=0;
unsigned int signal_jednicka=0;
unsigned int hodnota_timeru=0;
unsigned int strida=0;
char char_teplota[6];
char nula[6];
char jednicka[6];

int main(void)
{
DDRD &= ~(1<<PD3); //nastaveni vstupu pinuPD3,INIT1
LCDinit(); // inicializace displeje
TCCR1B |= ((1 << CS10)); // žádná dělička
MCUCR |= (1<<ISC10); // přerušení při každé hraně
GICR |= (1<<INT1); // povolení INT1
sei(); // povolení přerušení
while(1)
{
/strida = signal_jednicka/(signal_jednicka+signal_nula); // výpočet střídy
teplota = (strida - 0.32)/0.0047;
/ // a teploty
itoa(signal_nula,nula,10); // konverze signálu v 0
LCDGotoXY(0,0); // výpis na
LCDstring(nula,6); // display
itoa(signal_jednicka,jednicka,10); // výpis na
LCDGotoXY(7,0); // display
LCDstring(jednicka,6);
}
}

ISR(SIG_INTERRUPT1)
{
hodnota_timeru = TCNT1; // cteni timeru
if(PD3>0) // když je přerušení z vzestupné hrany tak byla předtím nula
{signal_nula = hodnota_timeru;}
else{signal_jednicka = hodnota_timeru;} // když je přerušení z sestupné hrany tak byla předtím jednička
TCNT1=0;
}[/code]

vopred sa ospravedlnujem za prispevok od veci:
Ta frekvencia interneho KRYSTALU je az dych vyrazajuca…

Ježkovy, sorry jasně že jen 1MHz :wink:.

if(PD3>0)

PD3 je konstanta s hodnotou 3.
Takže podmínka je vždy pravdivá.

Můžeš použít

if(bit_is_set(PORTD,3))

Upravil jsem podmínku, ale stále to neumí rozlišit. Cpe obě hodnoty jak 0 tak 1 do jedné proměnné takže na displeji je jedna proměnná 0 a v druhé se střídá 151 a 113 což po dosazení do vzorce na výpočet teploty je

střída = 113/(151+113) = 0.428
teplota = (střída -0.32)/0.0047 = 22.98°C což vychází, protože momentálně svítím blízko lampičkou, jinak to bylo odpoledne okolo 20 stupňů.

Mohl bych použít 2 8-bitové timery, jen jsem to chtěl zkusit, jestli to nejde s jedním 16-bitovým kvůli menší chybě, jestli s tím nemáte někdo zkušenosti? Bohužel atmega16 2-16bitové nemá no. Ale jinak díky moc za úpravu podmínky :wink:

  1. Proměnné použité v hlavním programu i v přerušení musí být deklarovány jako volatile.

volatile unsigned int signal_nula=0; volatile unsigned int signal_jednicka=0;

  1. Vícebajtová proměnná, která může být změněna v přerušení, musí být v hlavním programu čtena atomicky. Zní to vědecky, ale znamená to jenom že během čtení musíme zakázat přerušení.

main() { ... cli(); strida = signal_jednicka/(signal_jednicka+signal_nula); sei();

Pro zobrazení ti stačí jeden string, např. takto

char displej[17];
...
itoa(signal_nula,displej,10);    // konverze signálu v 0
  LCDstring(displej);            
  itoa(signal_jednicka,displej,10); 
  LCDstring(displej); 
...

Díky moc, na to zastavení přerušení jsem úplně zapomněl :wink: až teď si vzpomínám, že jsem na to v datasheetu už narazil. Ta číselná hodnota v LCDstring(něco,*) funkci je proto kolik písmen se má zobrazit. Třeba jako efekt s postupně nabíhajícími písmenky :wink: např po nějakém určeném časovém intervalu.

Díky moc, na to zastavení přerušení jsem úplně zapomněl :wink: až teď si vzpomínám, že jsem na to v datasheetu už narazil. Ta číselná hodnota v LCDstring(něco,*) funkci je proto kolik písmen se má zobrazit. Třeba jako efekt s postupně nabíhajícími písmenky :wink: např po nějakém určeném časovém intervalu.

Na ATOMIC nepouzivaj zakaz a opatovne povolenie globalneho prerusenia.

V GCC je na to struktura

ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
// ....
}

umoznuje z bloku vystupovat na viacerych miestach bez potreby “rucneho” povolovania prerusenia. Nie nevyhnutne az na konci. Vid priklad. Jedna sa o uryvok z rozsiahlejsieho cyklu.

ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
		// zistenie o ktory kanal sa jedna
	   p_klient_port_pom = (STRUCT_PORT_KLIENT *)p_klient_port_struct;
		p_klient_command_pom = (STRUCT_COMMAND_TWI *)p_klient_port_pom->p_command;
		asm volatile ("" : : : "memory");
		kanal = p_klient_command_pom->kanal;
		asm volatile ("" : : : "memory");
		if (kanal >= MAX_POCET_TWI) return(ANS_END_PORT_NOT_EXIST);

		if (port_status[kanal] != PORT_FREE) return(ANS_BUSY);
		port_status[kanal] = PORT_BUSY;

		p_klient_port[kanal] = (STRUCT_PORT_KLIENT *)p_klient_port_struct;
		asm volatile ("" : : : "memory");
		klient_ident[kanal] = p_klient_port[kanal]->ident;
		p_klient_command[kanal] = p_klient_command_pom;
		klient_prikaz[kanal] = p_klient_command_pom->prikaz;
		klient_pocet_out[kanal] = p_klient_command_pom->pocet_out;
		klient_pocet_in[kanal] = p_klient_command_pom->pocet_in;
		klient_cnt_tx_rx_bajty[kanal] = 0;
		klient_max_buffer[kanal] = p_klient_command_pom->max_buffer;
		p_klient_data[kanal] = (uint8_t*)p_klient_command_pom->p_data;
		p_klient_data_prac[kanal] = p_klient_data[kanal];
		return(ANS_RUN);
}

Díky moc všem :wink:. Nakonec se mi to podařilo rozběhnout. Chyba teploty je okolo stupně a půl nahoru i dolů :wink:. To se ale dalo čekat :wink:. Zkusím to ještě vyladit. Kdybyste chtěli, tak sem můžu hodit zdroják.

Chapem Tvoju radost, ale nemusis to sem preto posielat az 3x :slight_smile: :slight_smile: :slight_smile:

Omlouvám se, ale už to nemůžu smazat :frowning:. Nechápu, jak se to mohlo stát posílal jsem to jen 1x.

:arrow_right: administrator: smazáno

Mozno intergalakticka ozvena :slight_smile: