Portál AbcLinuxu, 10. listopadu 2025 20:06
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "onewire.h"
#include "ds18x20.h"
#include "main.h"
uint8_t gSensorIDs[MAXSENSORS][OW_ROMCODE_SIZE];
int8_t akva1_id = -1, akva2_id = -1, lednice_id = -1;
uint16_t akva1_teplota = 0, akva2_teplota = 0, lednice_teplota = 0;
uint16_t akva1_teplota_cilova = 0, akva2_teplota_cilova = 0, lednice_teplota_cilova = 0;
uint8_t akva1_tolerance_chyb = 0, akva2_tolerance_chyb = 0, lednice_tolerance_chyb = 0, celkova_tolerance_chyb = 0;
bool countdown_akva1 = false, countdown_akva2 = false;
bool akva1_hromadne_tlacitko_stisknuto = false, akva2_hromadne_tlacitko_stisknuto = false;
uint8_t leds_array[LEDS];
uint8_t leds_array_pointer = 0;
uint8_t citac = 0, citac2 = 0;
uint16_t timeout_akva1 = 0, timeout_akva2 = 0;
void m_delay_ms(unsigned int ms) {
unsigned int i;
for ( i=0; i<ms; i++) { _delay_ms(1); }
}
void m_delay_s(unsigned int s) {
unsigned int i, i2;
for ( i=0; i<s; i++) { for ( i2=0; i2<100; i2++) { _delay_ms(10); } }
}
void led_alert() {
bool retrOn = bit_is_set(LED_PIN, LED_AKVA1);
bitSet (LED_PORT, LED_AKVA1);
m_delay_ms(100);
bitClear (LED_PORT, LED_AKVA1);
_delay_ms(100);
if(retrOn) bitSet(LED_PORT, LED_AKVA1);
}
void leds_add(uint8_t lid) {
if( leds_array_pointer < LEDS ) {
leds_array[leds_array_pointer] = lid;
leds_array_pointer ++;
}
}
void leds_clear() {
leds_array_pointer = 0;
}
void leds_blink(uint8_t interval) {
bool leds_status_before[LEDS];
if(leds_array_pointer > 0) {
for(int i=0; i<leds_array_pointer; i++) {
if(bit_is_set(LED_PIN, leds_array[i]))
leds_status_before[i] = true;
else
leds_status_before[i] = false;
bitSet (LED_PORT, leds_array[i]);
}
m_delay_ms(interval);
for(int i=0; i<leds_array_pointer; i++) {
bitClear (LED_PORT, leds_array[i]);
}
m_delay_ms(interval);
for(int i=0; i<leds_array_pointer; i++) {
if(leds_status_before[i]) bitSet (LED_PORT, leds_array[i]);
}
leds_clear();
}
}
void leds_search() {
for(int i=0; i<LEDS; i++) {
bitSet(LED_PORT, i);
m_delay_ms(LED_BLINK_INTERVAL);
bitClear(LED_PORT, i);
}
}
void rele_on(uint8_t rr) {
m_delay_ms(600);
bitSet(RELE_PORT,rr);
}
void rele_off(uint8_t rr) {
m_delay_ms(400);
bitClear(RELE_PORT,rr);
}
uint8_t search_sensors(void) {
uint8_t i;
uint8_t id[OW_ROMCODE_SIZE];
uint8_t diff, nSensors;
bool akva1, akva2, lednice;
while(1) {
nSensors = 0;
for(diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE && nSensors < MAXSENSORS; ) {
DS18X20_find_sensor( &diff, &id[0] );
if( diff == OW_PRESENCE_ERR ) break;
if( diff == OW_DATA_ERR ) break;
akva1 = true;
akva2 = true;
lednice = true;
for (i=0;i<OW_ROMCODE_SIZE;i++) {
gSensorIDs[nSensors][i]=id[i];
if(akva1) {
while(!eeprom_is_ready()) { _delay_ms(10); }
if( gSensorIDs[nSensors][i] != eeprom_read_byte((uint8_t*)(EEPROM_AKVA1+i)) ) akva1 = false;
}
if(akva2) {
while(!eeprom_is_ready()) { _delay_ms(10); }
if( gSensorIDs[nSensors][i] != eeprom_read_byte((uint8_t*)(EEPROM_AKVA2+i)) ) akva2 = false;
}
if(lednice) {
while(!eeprom_is_ready()) { _delay_ms(10); }
if( gSensorIDs[nSensors][i] != eeprom_read_byte((uint8_t*)(EEPROM_LEDNICE+i)) ) lednice = false;
}
}
if(akva1 && !akva2 && !lednice) {
akva1_id = nSensors;
leds_add(LED_AKVA1);
}
if(!akva1 && akva2 && !lednice) {
akva2_id = nSensors;
leds_add(LED_AKVA2);
}
if(!akva1 && !akva2 && lednice) {
lednice_id = nSensors;
leds_add(LED_LEDNICE);
}
nSensors++;
}
if( nSensors ) return nSensors;
leds_search();
leds_blink(LED_BLINK_FAST_INTERVAL);
m_delay_s(1);
}
}
void uloz_senzor( uint8_t *id, uint8_t kam ) {
for (int i=0; i<OW_ROMCODE_SIZE; i++) {
while(!eeprom_is_ready()) { _delay_ms(10); }
eeprom_write_byte((uint8_t*)(kam+i),id[i]);
}
}
void vymaz_eeprom() {
for (int i=0; i<OW_ROMCODE_SIZE*3; i++) {
while(!eeprom_is_ready()) { _delay_ms(10); }
eeprom_write_byte((uint8_t*)i,0x00);
}
}
void programovaci_mod(uint8_t nSensors) {
uint8_t i;
uint8_t subzero, cel, cel_frac_bits;
bitSet(LED_PORT,LED_AKVA1);
m_delay_s(5);
bitSet(LED_PORT,LED_AKVA2);
m_delay_s(5);
bitClear(LED_PORT,LED_AKVA1);
bitClear(LED_PORT,LED_AKVA2);
vymaz_eeprom();
bitSet(LED_PORT,LED_LEDNICE);
m_delay_s(1);
bitClear(LED_PORT,LED_LEDNICE);
uint16_t puvodni_teplota[nSensors];
bool saved_lednice = false, saved_akva1 = false, saved_akva2 = false;
if ( DS18X20_start_meas( DS18X20_POWER_PARASITE, NULL ) == DS18X20_OK ) {
_delay_ms(DS18B20_TCONV_12BIT);
for ( i=0; i<nSensors; i++ ) {
if ( DS18X20_read_meas( &gSensorIDs[i][0], &subzero, &cel, &cel_frac_bits) == DS18X20_OK ) {
puvodni_teplota[i] = DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits);
}
else {
while(1) { led_alert(); }
}
}
}
else {
while(1) { led_alert(); }
}
while(1) {
if ( DS18X20_start_meas( DS18X20_POWER_PARASITE, NULL ) == DS18X20_OK ) {
_delay_ms(DS18B20_TCONV_12BIT);
for ( i=0; i<nSensors; i++ ) {
if ( DS18X20_read_meas( &gSensorIDs[i][0], &subzero, &cel, &cel_frac_bits) == DS18X20_OK ) {
if( DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits) > puvodni_teplota[i] ) {
if( (DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits) - puvodni_teplota[i]) >= 100 ) {
if( (bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA1_ZVYSIT) ||
bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA1_SNIZIT)) &&
(bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA2_ZVYSIT) ||
bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA2_SNIZIT)) && !saved_lednice) {
bitSet(LED_PORT,LED_LEDNICE);
uloz_senzor(&gSensorIDs[i][0], EEPROM_LEDNICE);
puvodni_teplota[i] = 2000;
saved_lednice = true;
m_delay_s(2);
bitClear(LED_PORT,LED_LEDNICE);
}
else if( (bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA1_ZVYSIT) ||
bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA1_SNIZIT)) && !saved_akva1) {
bitSet(LED_PORT,LED_AKVA1);
uloz_senzor(&gSensorIDs[i][0], EEPROM_AKVA1);
puvodni_teplota[i] = 2000;
saved_akva1 = true;
m_delay_s(2);
bitClear(LED_PORT,LED_AKVA1);
}
else if( (bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA2_ZVYSIT) ||
bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA2_SNIZIT)) && !saved_akva2) {
bitSet(LED_PORT,LED_AKVA2);
uloz_senzor(&gSensorIDs[i][0], EEPROM_AKVA2);
puvodni_teplota[i] = 2000;
saved_akva2 = true;
m_delay_s(2);
bitClear(LED_PORT,LED_AKVA2);
}
}
}
}
else led_alert();
}
}
else led_alert();
leds_add(LED_AKVA1);
leds_add(LED_AKVA2);
leds_add(LED_LEDNICE);
leds_blink(LED_BLINK_FAST_INTERVAL);
}
}
ISR(TIMER0_OVF_vect) { // zavola se pri preteceni interniho 8bit citace
TCNT0=6; // (8MHz/1024/250=31,25[tzn. 125 za 4 sekundy]) preruseni/sec - pocita s nastavenim interniho oscilatoru na
// 8MHz. Pokud tak neni, je nutne prepocitat
// 256 (velikost counteru) - 250 (nas delitel) = 6 (pri kazdem preteceni
// zaciname od 6 a ne od 0)
if(++citac>=125) {
if(countdown_akva1) {
if(timeout_akva1>3)
timeout_akva1 -= 4;
else {
timeout_akva1 = 0;
countdown_akva1 = false;
}
}
if(countdown_akva2) {
if(timeout_akva2>3)
timeout_akva2 -= 4;
else {
timeout_akva2 = 0;
countdown_akva2 = false;
}
}
citac = 0;
}
if(bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA1_ZVYSIT) && bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA1_SNIZIT)) {
akva1_hromadne_tlacitko_stisknuto = true;
}
else if(akva1_hromadne_tlacitko_stisknuto) {
akva1_hromadne_tlacitko_stisknuto = false;
if(countdown_akva1)
countdown_akva1 = false;
else {
timeout_akva1 = TEPLOTA_UP_TIMEOUT;
countdown_akva1 = true;
}
}
if(bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA2_ZVYSIT) && bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA2_SNIZIT)) {
akva2_hromadne_tlacitko_stisknuto = true;
}
else if(akva2_hromadne_tlacitko_stisknuto) {
akva2_hromadne_tlacitko_stisknuto = false;
if(countdown_akva2)
countdown_akva2 = false;
else {
timeout_akva2 = TEPLOTA_UP_TIMEOUT;
countdown_akva2 = true;
}
}
}
// blikani ledek
ISR(TIMER2_OVF_vect) { // zavola se pri preteceni interniho 8bit citace
TCNT2=0; // (8MHz/1024/256=cca30,52) preruseni/sec - pocita s nastavenim interniho oscilatoru na
// 8MHz. Pokud tak neni, je nutne prepocitat
// 256 (velikost counteru) - 250 (nas delitel) = 6 (pri kazdem preteceni
// zaciname od 6 a ne od 0)
if(++citac2 == 20) {
if(countdown_akva1) leds_add(LED_AKVA1);
if(countdown_akva2) leds_add(LED_AKVA2);
leds_blink(LED_BLINK_INTERVAL);
}
if(citac2 == 40) {
if(akva1_tolerance_chyb == 0) leds_add(LED_AKVA1);
if(akva2_tolerance_chyb == 0) leds_add(LED_AKVA2);
if(lednice_tolerance_chyb == 0) leds_add(LED_LEDNICE);
leds_blink(LED_BLINK_FAST_INTERVAL);
if(celkova_tolerance_chyb == 0) {
leds_add(LED_LEDNICE);
leds_blink(LED_BLINK_INTERVAL);
}
}
if(citac2 > 60) citac2 = 0;
}
int main () {
// Vystupni piny
bitSet (DDRC, 0);
bitSet (DDRC, 1);
bitSet (DDRC, 2);
bitSet (DDRC, 3);
bitSet (DDRC, 4);
bitSet (DDRC, 5);
// Vstupni piny
bitClear (DDRD, 0);
bitSet (PORTD, 0);
bitClear (DDRD, 1);
bitSet (PORTD, 1);
bitClear (DDRD, 2);
bitSet (PORTD, 2);
bitClear (DDRD, 3);
bitSet (PORTD, 3);
uint8_t nSensors;
uint8_t subzero, cel, cel_frac_bits;
bool akva1_teplota_hyst = true, akva2_teplota_hyst = true, lednice_teplota_hyst = true;
nSensors = search_sensors();
// rezim programovani eeprom / uceni se senzoru
if(bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA1_ZVYSIT) && bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA1_SNIZIT) &&
bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA2_ZVYSIT) && bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA2_SNIZIT)) {
programovaci_mod(nSensors);
}
bitSet(TCCR0, CS02); // Clock prescaler (/ 1024)
bitSet(TCCR0, CS00); // Clock prescaler (/ 1024)
bitSet(TIMSK, TOIE0); // povoleni preruseni od casovace
bitSet(TCCR2, CS22); // Clock prescaler (/ 1024)
bitSet(TCCR2, CS21); // Clock prescaler (/ 1024)
bitSet(TCCR2, CS20); // Clock prescaler (/ 1024)
bitSet(TIMSK, TOIE2); // povoleni preruseni od casovace
sei();
while(1) {
if ( DS18X20_start_meas( DS18X20_POWER_PARASITE, NULL ) == DS18X20_OK ) {
celkova_tolerance_chyb = TOLERANCE_CHYB;
_delay_ms(DS18B20_TCONV_12BIT);
if(akva1_id > -1 && DS18X20_read_meas( &gSensorIDs[akva1_id][0], &subzero, &cel, &cel_frac_bits) == DS18X20_OK) {
if(subzero)
akva1_teplota = 0;
else
akva1_teplota = DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits);
akva1_tolerance_chyb = TOLERANCE_CHYB;
}
else {
if(akva1_tolerance_chyb > 0)
akva1_tolerance_chyb --;
else
akva1_teplota = 0;
}
_delay_ms(DS18B20_TCONV_12BIT);
if(akva2_id > -1 && DS18X20_read_meas( &gSensorIDs[akva2_id][0], &subzero, &cel, &cel_frac_bits) == DS18X20_OK) {
if(subzero)
akva2_teplota = 0;
else
akva2_teplota = DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits);
akva2_tolerance_chyb = TOLERANCE_CHYB;
}
else {
if(akva2_tolerance_chyb > 0)
akva2_tolerance_chyb --;
else
akva2_teplota = 0;
}
_delay_ms(DS18B20_TCONV_12BIT);
if(lednice_id > -1 && DS18X20_read_meas( &gSensorIDs[lednice_id][0], &subzero, &cel, &cel_frac_bits) == DS18X20_OK) {
if(subzero)
lednice_teplota = 0;
else
lednice_teplota = DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits);
lednice_tolerance_chyb = TOLERANCE_CHYB;
}
else {
if(lednice_tolerance_chyb > 0)
lednice_tolerance_chyb --;
else
lednice_teplota = 0;
}
// nastaveni teplot
if(akva1_teplota_hyst)
akva1_teplota_cilova = AKVA1_DEFAULT+(HYST/2);
else
akva1_teplota_cilova = AKVA1_DEFAULT-(HYST/2);
if(bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA1_ZVYSIT))
akva1_teplota_cilova += 10;
else if(bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA1_SNIZIT))
akva1_teplota_cilova -= 10;
if(countdown_akva1)
akva1_teplota_cilova += TEPLOTA_UP_VALUE;
if(akva2_teplota_hyst)
akva2_teplota_cilova = AKVA2_DEFAULT+(HYST/2);
else
akva2_teplota_cilova = AKVA2_DEFAULT-(HYST/2);
if(bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA2_ZVYSIT))
akva2_teplota_cilova += 10;
else if(bit_is_clear(TLACITKA_PIN, TLACITKO_AKVA2_SNIZIT))
akva2_teplota_cilova -= 10;
if(countdown_akva2)
akva2_teplota_cilova += TEPLOTA_UP_VALUE;
if(lednice_teplota_hyst)
lednice_teplota_cilova = 30; // +3
else
lednice_teplota_cilova = 0; // +0
// ovladani relatek
if(akva1_teplota > akva1_teplota_cilova) {
rele_on(RELE_AKVA1);
bitSet (LED_PORT, LED_AKVA1);
akva1_teplota_hyst = false;
}
else {
rele_off(RELE_AKVA1);
bitClear (LED_PORT, LED_AKVA1);
akva1_teplota_hyst = true;
}
if(akva2_teplota > akva2_teplota_cilova) {
rele_on(RELE_AKVA2);
bitSet (LED_PORT, LED_AKVA2);
akva2_teplota_hyst = false;
}
else {
rele_off(RELE_AKVA2);
bitClear (LED_PORT, LED_AKVA2);
akva2_teplota_hyst = true;
}
// lednice
if( bit_is_set(RELE_PIN, RELE_AKVA1) || bit_is_set(RELE_PIN, RELE_AKVA2) ) {
if(lednice_teplota > lednice_teplota_cilova ) {
rele_on(RELE_LEDNICE);
bitSet (LED_PORT, LED_LEDNICE);
lednice_teplota_hyst = false;
}
else {
rele_off(RELE_LEDNICE);
bitClear (LED_PORT, LED_LEDNICE);
lednice_teplota_hyst = true;
}
}
else {
rele_off(RELE_LEDNICE);
bitClear (LED_PORT, LED_LEDNICE);
lednice_teplota_hyst = false;
}
// while(!eeprom_is_ready()) { _delay_ms(10); }
// eeprom_write_byte(50,(uint8_t)(akva1_teplota/2));
// while(!eeprom_is_ready()) { _delay_ms(10); }
// eeprom_write_byte(51,(uint8_t)(akva2_teplota/2));
// while(!eeprom_is_ready()) { _delay_ms(10); }
// eeprom_write_byte(52,(uint8_t)(lednice_teplota/2));
// for(int i=0; i<1000; i++) { m_delay_s(100); }
}
else {
if(celkova_tolerance_chyb > 0)
celkova_tolerance_chyb --;
else {
rele_off(RELE_AKVA1);
rele_off(RELE_AKVA2);
rele_off(RELE_LEDNICE);
}
}
//m_delay_s(1);
}
return 0;
}
main.h
#define bitSet(var, mask) ((var) |= (1 << (mask))) #define bitClear(var, mask) ((var) &= ~(1 << (mask))) #define MAXSENSORS 5 #define EEPROM_AKVA1 0 #define EEPROM_AKVA2 OW_ROMCODE_SIZE #define EEPROM_LEDNICE 2*OW_ROMCODE_SIZE #define RELE_PORT PORTC #define RELE_PIN PINC #define RELE_AKVA1 3 #define RELE_AKVA2 4 #define RELE_LEDNICE 5 #define LEDS 3 // pocet ledek #define LED_BLINK_INTERVAL 100 // doba rozsviceni led pri blikani v ms #define LED_BLINK_FAST_INTERVAL 50 #define LED_PORT PORTC #define LED_PIN PINC #define LED_AKVA1 2 #define LED_AKVA2 1 #define LED_LEDNICE 0 #define TLACITKA_PORT PORTD #define TLACITKA_PIN PIND #define TLACITKO_AKVA1_ZVYSIT 3 #define TLACITKO_AKVA1_SNIZIT 2 #define TLACITKO_AKVA2_ZVYSIT 1 #define TLACITKO_AKVA2_SNIZIT 0 #define HYST 4 // pasmo necitlivosti 4/10 = 0,4˚C #define AKVA1_DEFAULT 260 // defautlne se bude udrzovat 26˚C #define AKVA2_DEFAULT 260 // defautlne se bude udrzovat 26˚C #define TEPLOTA_UP_TIMEOUT 28800 // docasne zvyseni teploty po dobu cca 28800 sekund = 8 hodin #define TEPLOTA_UP_VALUE 20 // docasne zvyseni teploty o 2˚C #define TOLERANCE_CHYB 6 // kolik chyb mereni je povoleno, nez je predchozi mereni zahozeno
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.