Zamiennik licznika impulsów DS2423 na ATtiny25

Układ DS2423 jest kompatybilnym z magistralą 1 wire podwójnym licznikiem impulsów z 4KB pamięci RAM. Na nieszczęście jego producent, firma Maxim, wycofała się z jego produkcji kilka lat temu i obecnie jest on praktycznie niedostępny na rynku. Przedstawiam sposób na „naśladowanie” układu za pomocą mikrokontrolera ATtiny25.

DS2423 jest tak poszukiwany przede wszystkim ze względu na swoje działanie jako podwójny licznik impulsów. Znajduje on zastosowanie w obrotomierzach, wiatromierzach, deszczomierzach, licznikach osób przechodzących przez bramki a także w „domach inteligentnych” – jako licznik impulsów z wodomierza oraz liczników zużycia gazu i energii elektrycznej.

Jego produkcja została zakończona ponad 4 lata temu, co przy ogromnym zapotrzebowaniu oznacza, że zapasy magazynowe kurczą się w zastraszającym tempie a cena cały czas rośnie. Na chwilę obecną udało mi się znaleźć jedno miejsce w sieci, gdzie można go kupić – jest to sklep z podzespołami elektronicznymi w USA. Kosztuje on tam ponad 10$, oczywiście plus koszty wysyłki.

Ponieważ 1wire jest protokołem komunikacji opatentowanym przez firmę Dallas Semiconductors, żaden inny producent nie otrzymał zezwolenia na masową produkcję układów klienckich (slave) kompatybilnych z tym standardem. Warto w tym momencie wspomnieć w skrócie o tym, jak jest zorganizowana komunikacja w standardzie 1wire. Każde podpięte urządzenie identyfikuje się 64-bitowym ID, z czego pierwsze 8 bitów to identyfikator typu urządzenia, kolejne 48 bitów to unikatowy ID danego chipa (nie ma dwóch układów o takim samym identyfikatorze na świecie) oraz 8-bitowa suma kontrolna CRC. Według producenta, gdyby standard 1wire został „uwolniony”, rynek zalałyby urządzenia o identyfikatorze grupy zgodnym z istniejącymi produktami Dallasa, a także produkowane masowo chipy o takim samym identyfikatorze, co spowodowałoby możliwość wystąpienia konfliktów podczas podłączania wielu urządzeń do jednej magistrali.

Protokół 1wire został jednak „rozgryziony” przez wielu programistów na świecie i powstały liczne jego implementacje na tanie i łatwo dostępne mikroprocesory. Jednym z takich programów jest napisana przez Tobiasa Müllera implementacja licznika impulsów DS2423 na ATtiny25. Mogę się tylko domyślać, że właśnie ATtiny25 został wybrany nieprzypadkowo. Jest to jeden z najtańszych i najmniejszych mikrokontrolerów w ofercie firmy Atmel – najpopularniejszego producenta tego typu urządzeń.

Co więcej, wielu elektroników amatorów miało styczność z kostkami z rodziny ATmega lub ATtiny i posiada choćby najprostszy programator ISP. Dzięki temu „przygotowanie” własnego zamiennika dla DS2423 jest tańsze i szybsze niż kupno prawdziwego chipa. Prawidłowo zaprogramowana kość i podłączona do magistrali 1 wire jest rozpoznawana przez OneWireViewer oraz OWFS jako układ DS2423.

Układ wymaga wyłącznie dwóch zewnętrznych elementów, typowych dla każdego mikroprocesora: kondensatora 100nF blisko nóżek zasilania oraz opornika w zakresie 4,7 – 10k, podciągającego pin RESET do zasilania. 64-bajtowy licznik zlicza przejścia z logicznej „jedynki” na zero, a jego zawartość jest resetowana po utracie zasilania. W załączniku gotowy plik .hex ze skompilowanym programem, który należy wgrać na ATtiny25. Program działa na fabrycznych fusebitach. Załączam również kod źródłowy, w którym można zmienić identyfikator urządzenia, w przypadku podłączania więcej niż jednej sztuki do magistrali. Identyfikator zmienia się w linii 211 kodu, modyfikując poszczególne bajty oraz sumę CRC.

NIE JESTEM AUTOREM KODU ŹRÓDŁOWEGO!

//owdevice - A small 1-Wire emulator for AVR Microcontroller
//
//Copyright (C) 2012  Tobias Mueller mail (at) tobynet.de
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
// any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
//
//VERSION 1.2 DS2423  for ATTINY2313 and ATTINY25

//FOR MAKE by hand
/*
avr-gcc -mmcu=[attiny25|attiny2313] -O2 -c ow_slave_DS2423.c
avr-gcc.exe -mmcu=[attiny25|attiny2313]  ow_slave_DS2423.o -o ow_slave_DS2423.elf
avr-objcopy -O ihex  ow_slave_DS2423.elf ow_slave_DS2423.hex
*/

#include <avr/io.h>
#include <avr/interrupt.h>
//does not work here because less memory by ATtiny13
#if defined(__AVR_ATtiny13A__) || defined(__AVR_ATtiny13__)
// OW_PORT Pin 6  - PB1
//Analog input PB2

//OW Pin
#define OW_PORT PORTB //1 Wire Port
#define OW_PIN PINB //1 Wire Pin as number
#define OW_PORTN (1<<PINB1)  //Pin as bit in registers
#define OW_PINN (1<<PINB1)
#define OW_DDR DDRB  //pin direction register
#define SET_LOW OW_DDR|=OW_PINN;OW_PORT&=~OW_PORTN;  //set 1-Wire line to low
#define RESET_LOW {OW_DDR&=~OW_PINN;}  //set 1-Wire pin as input
//Pin interrupt
#define EN_OWINT {GIMSK|=(1<<INT0);GIFR|=(1<<INTF0);}  //enable interrupt
#define DIS_OWINT  GIMSK&=~(1<<INT0);  //disable interrupt
#define SET_RISING MCUCR=(1<<ISC01)|(1<<ISC00);  //set interrupt at rising edge
#define SET_FALLING MCUCR=(1<<ISC01); //set interrupt at falling edge
#define CHK_INT_EN (GIMSK&(1<<INT0))==(1<<INT0) //test if interrupt enabled
#define PIN_INT ISR(INT0_vect)  // the interrupt service routine
//Timer Interrupt
#define EN_TIMER {TIMSK0 |= (1<<TOIE0); TIFR0|=(1<<TOV0);} //enable timer interrupt
#define DIS_TIMER TIMSK0  &= ~(1<<TOIE0); // disable timer interrupt
#define TCNT_REG TCNT0  //register of timer-counter
#define TIMER_INT ISR(TIM0_OVF_vect) //the timer interrupt service routine

//Initializations of AVR
#define INIT_AVR CLKPR=(1<<CLKPCE);\
CLKPR=0;/*9.6Mhz*/\
TIMSK0=0;\
GIMSK=(1<<INT0);/*set direct GIMSK register*/\
TCCR0B=(1<<CS00)|(1<<CS01); /*9.6mhz /64 couse 8 bit Timer interrupt every 6,666us*/

//Times
#define OWT_MIN_RESET 51 //minimum duration of the Reset impulse

#define OWT_RESET_PRESENCE 4 //time between rising edge of reset impulse and presence impulse
#define OWT_PRESENCE 20 //duration of the presence impulse
#define OWT_READLINE 4  //duration from master low to read the state of 1-Wire line
#define OWT_LOWTIME 4 //length of low
#endif

#ifdef __AVR_ATtiny25__
// OW_PORT Pin 7  - PB2

//OW Pin
#define OW_PORT PORTB //1 Wire Port
#define OW_PIN PINB //1 Wire Pin as number
#define OW_PORTN (1<<PINB2)  //Pin as bit in registers
#define OW_PINN (1<<PINB2)
#define OW_DDR DDRB  //pin direction register
#define SET_LOW OW_DDR|=OW_PINN;OW_PORT&=~OW_PORTN;  //set 1-Wire line to low
#define RESET_LOW {OW_DDR&=~OW_PINN;}  //set 1-Wire pin as input
//Pin interrupt
#define EN_OWINT {GIMSK|=(1<<INT0);GIFR|=(1<<INTF0);}  //enable interrupt
#define DIS_OWINT  GIMSK&=~(1<<INT0);  //disable interrupt
#define SET_RISING MCUCR=(1<<ISC01)|(1<<ISC00);  //set interrupt at rising edge
#define SET_FALLING MCUCR=(1<<ISC01); //set interrupt at falling edge
#define CHK_INT_EN (GIMSK&(1<<INT0))==(1<<INT0) //test if interrupt enabled
#define PIN_INT ISR(INT0_vect)  // the interrupt service routine
//Timer Interrupt
#define EN_TIMER {TIMSK |= (1<<TOIE0); TIFR|=(1<<TOV0);} //enable timer interrupt
#define DIS_TIMER TIMSK  &= ~(1<<TOIE0); // disable timer interrupt
#define TCNT_REG TCNT0  //register of timer-counter
#define TIMER_INT ISR(TIM0_OVF_vect) //the timer interrupt service routine

#define OWT_MIN_RESET 51
#define OWT_RESET_PRESENCE 4
#define OWT_PRESENCE 20
#define OWT_READLINE 3 //for fast master, 4 for slow master and long lines
#define OWT_LOWTIME 3 //for fast master, 4 for slow master and long lines

//Initializations of AVR
#define INIT_AVR CLKPR=(1<<CLKPCE); \
CLKPR=0; /*8Mhz*/  \
TIMSK=0; \
GIMSK=(1<<INT0);  /*set direct GIMSK register*/ \
TCCR0B=(1<<CS00)|(1<<CS01); /*8mhz /64 couse 8 bit Timer interrupt every 8us*/

#define PC_INT_ISR ISR(PCINT0_vect) { /*ATT25 with 0 by PCINT*/ \
if (((PINB&(1<<PINB3))==0)&&((istat&(1<<PINB3))==(1<<PINB3))) {	Counter0++;	}		\
if (((PINB&(1<<PINB4))==0)&&((istat&(1<<PINB4))==(1<<PINB4))) {	Counter1++;	}		\
istat=PINB;}	\

#define INIT_COUNTER_PINS /* Counter Interrupt */\
GIMSK|=(1<<PCIE);\
PCMSK=(1<<PCINT3)|(1<<PCINT4);	\
DDRB &=~((1<<PINB3)|(1<<PINB4)); \
istat=PINB;\

#endif // __AVR_ATtiny25__

#if defined(__AVR_ATtiny2313A__) || defined(__AVR_ATtiny2313__)
// OW_PORT Pin 6  - PD2

//OW Pin
#define OW_PORT PORTD //1 Wire Port
#define OW_PIN PIND //1 Wire Pin as number
#define OW_PORTN (1<<PIND2)  //Pin as bit in registers
#define OW_PINN (1<<PIND2)
#define OW_DDR DDRD  //pin direction register
#define SET_LOW OW_DDR|=OW_PINN;OW_PORT&=~OW_PORTN;  //set 1-Wire line to low
#define RESET_LOW {OW_DDR&=~OW_PINN;}  //set 1-Wire pin as input
//Pin interrupt
#define EN_OWINT {GIMSK|=(1<<INT0);EIFR|=(1<<INTF0);}  //enable interrupt
#define DIS_OWINT  GIMSK&=~(1<<INT0);  //disable interrupt
#define SET_RISING MCUCR|=(1<<ISC01)|(1<<ISC00);  //set interrupt at rising edge
#define SET_FALLING {MCUCR|=(1<<ISC01);MCUCR&=~(1<<ISC00);} //set interrupt at falling edge
#define CHK_INT_EN (GIMSK&(1<<INT0))==(1<<INT0) //test if interrupt enabled
#define PIN_INT ISR(INT0_vect)  // the interrupt service routine
//Timer Interrupt
#define EN_TIMER {TIMSK |= (1<<TOIE0); TIFR|=(1<<TOV0);} //enable timer interrupt
#define DIS_TIMER TIMSK  &= ~(1<<TOIE0); // disable timer interrupt
#define TCNT_REG TCNT0  //register of timer-counter
#define TIMER_INT ISR(TIMER0_OVF_vect) //the timer interrupt service routine

#define OWT_MIN_RESET 51
#define OWT_RESET_PRESENCE 4
#define OWT_PRESENCE 20
#define OWT_READLINE 3 //for fast master, 4 for slow master and long lines
#define OWT_LOWTIME 3 //for fast master, 4 for slow master and long lines

//Initializations of AVR
#define INIT_AVR CLKPR=(1<<CLKPCE); \
CLKPR=0; /*8Mhz*/  \
TIMSK=0; \
GIMSK=(1<<INT0);  /*set direct GIMSK register*/ \
TCCR0B=(1<<CS00)|(1<<CS01); /*8mhz /64 couse 8 bit Timer interrupt every 8us*/

#define PC_INT_ISR ISR(PCINT_vect) { /*ATT2313 without 0 by PCINT*/ \
if (((PINB&(1<<PINB3))==0)&&((istat&(1<<PINB3))==(1<<PINB3))) {	Counter0++;	}		\
if (((PINB&(1<<PINB4))==0)&&((istat&(1<<PINB4))==(1<<PINB4))) {	Counter1++;	}		\
istat=PINB;}	\

#define INIT_COUNTER_PINS /* Counter Interrupt */\
GIMSK|=(1<<PCIE);\
PCMSK=(1<<PCINT3)|(1<<PCINT4);	\
DDRB &=~((1<<PINB3)|(1<<PINB4)); \
istat=PINB;\

#endif // __AVR_ATtiny2313__

//#define _ONE_DEVICE_CMDS_  //Commands for only one device on bus (Not tested)

typedef union {
volatile uint8_t bytes[13];//={1,1,2,0,0,0,0,0,0,0,0,5,5};
struct {
uint16_t addr;
uint8_t read;
uint32_t counter;
uint32_t zero;
uint16_t crc;
};
} counterpack_t;
counterpack_t counterpack;
volatile uint16_t scrc; //CRC calculation

volatile uint8_t lastcps;
volatile uint32_t Counter0;
volatile uint32_t Counter1;
volatile uint8_t istat;

volatile uint8_t cbuf; //Input buffer for a command
const uint8_t owid[8]={0x1D, 0xA2, 0xD9, 0x84, 0x00, 0x00, 0x02, 0x37};
//set your own ID http://www.tm3d.de/index.php/tools/14-crc8-berechnung
volatile uint8_t bitp;  //pointer to current Byte
volatile uint8_t bytep; //pointer to current Bit

volatile uint8_t mode; //state
volatile uint8_t wmode; //if 0 next bit that send the device is  0
volatile uint8_t actbit; //current
volatile uint8_t srcount; //counter for search rom

//States / Modes
#define OWM_SLEEP 0  //Waiting for next reset pulse
#define OWM_RESET 1  //Reset pulse received
#define OWM_PRESENCE 2  //sending presence pulse
#define OWM_READ_COMMAND 3 //read 8 bit of command
#define OWM_SEARCH_ROM 4  //SEARCH_ROM algorithms
#define OWM_MATCH_ROM 5  //test number
#define OWM_CHK_RESET 8  //waiting of rising edge from reset pulse
#define OWM_GET_ADRESS 6
#define OWM_READ_MEMORY_COUNTER 7
#define OWM_WRITE_SCRATCHPAD 9
#define OWM_READ_SCRATCHPAD 10

#ifdef _ONE_DEVICE_CMDS_
#define OWM_READ_ROM 50
#endif

//Write a bit after next falling edge from master
//its for sending a zero as soon as possible
#define OWW_NO_WRITE 2
#define OWW_WRITE_1 1
#define OWW_WRITE_0 0

PIN_INT {
uint8_t lwmode=wmode;  //let this variables in registers
uint8_t lmode=mode;
if ((lwmode==OWW_WRITE_0)) {SET_LOW;lwmode=OWW_NO_WRITE;}    //if necessary set 0-Bit
DIS_OWINT; //disable interrupt, only in OWM_SLEEP mode it is active
switch (lmode) {
case OWM_SLEEP:
TCNT_REG=~(OWT_MIN_RESET);
EN_OWINT; //other edges ?
break;
//start of reading with falling edge from master, reading closed in timer isr
case OWM_MATCH_ROM:  //falling edge wait for receive
case OWM_GET_ADRESS:
case OWM_READ_COMMAND:
TCNT_REG=~(OWT_READLINE); //wait a time for reading
break;
case OWM_SEARCH_ROM:   //Search algorithm waiting for receive or send
if (srcount<2) { //this means bit or complement is writing,
TCNT_REG=~(OWT_LOWTIME);
} else
TCNT_REG=~(OWT_READLINE);  //init for read answer of master
break;
#ifdef _ONE_DEVICE_CMDS_
case OWM_READ_ROM:
#endif
case OWM_READ_MEMORY_COUNTER: //a bit is sending
TCNT_REG=~(OWT_LOWTIME);
break;
case OWM_CHK_RESET:  //rising edge of reset pulse
SET_FALLING;
TCNT_REG=~(OWT_RESET_PRESENCE);  //waiting for sending presence pulse
lmode=OWM_RESET;
break;
}
EN_TIMER;
mode=lmode;
wmode=lwmode;

}

TIMER_INT {
uint8_t lwmode=wmode; //let this variables in registers
uint8_t lmode=mode;
uint8_t lbytep=bytep;
uint8_t lbitp=bitp;
uint8_t lsrcount=srcount;
uint8_t lactbit=actbit;
uint16_t lscrc=scrc;
//Ask input line sate
uint8_t p=((OW_PIN&OW_PINN)==OW_PINN);
//Interrupt still active ?
if (CHK_INT_EN) {
//maybe reset pulse
if (p==0) {
lmode=OWM_CHK_RESET;  //wait for rising edge
SET_RISING;
}
DIS_TIMER;
} else
switch (lmode) {
case OWM_RESET:  //Reset pulse and time after is finished, now go in presence state
lmode=OWM_PRESENCE;
SET_LOW;
TCNT_REG=~(OWT_PRESENCE);
DIS_OWINT;  //No Pin interrupt necessary only wait for presence is done
break;
case OWM_PRESENCE:
RESET_LOW;  //Presence is done now wait for a command
lmode=OWM_READ_COMMAND;
cbuf=0;lbitp=1;  //Command buffer have to set zero, only set bits will write in
break;
case OWM_READ_COMMAND:
if (p) {  //Set bit if line high
cbuf|=lbitp;
}
lbitp=(lbitp<<1);
if (!lbitp) { //8-Bits read
lbitp=1;
switch (cbuf) {
case 0x55:lbytep=0;lmode=OWM_MATCH_ROM;break;
case 0xF0:  //initialize search rom
lmode=OWM_SEARCH_ROM;
lsrcount=0;
lbytep=0;
lactbit=(owid[lbytep]&lbitp)==lbitp; //set actual bit
lwmode=lactbit;  //prepare for writing when next falling edge
break;
case 0xA5:
lmode=OWM_GET_ADRESS; //first the master send an address
lbytep=0;lscrc=0x7bc0; //CRC16 of 0xA5
counterpack.bytes[0]=0;
break;
#ifdef _ONE_DEVICE_CMDS_
case 0xCC:
lbytep=0;cbuf=0;lmode=OWM_READ_COMMAND;break;
case 0x33:
lmode=OWM_READ_ROM;
lbytep=0;
break;
#endif
default: lmode=OWM_SLEEP;  //all other commands do nothing
}
}
break;
case OWM_SEARCH_ROM:
RESET_LOW;  //Set low also if nothing send (branch takes time and memory)
lsrcount++;  //next search rom mode
switch (lsrcount) {
case 1:lwmode=!lactbit;  //preparation sending complement
break;
case 3:
if (p!=(lactbit==1)) {  //check master bit
lmode=OWM_SLEEP;  //not the same go sleep
} else {
lbitp=(lbitp<<1);  //prepare next bit 						if (lbitp==0) { 							lbitp=1; 							lbytep++; 							if (lbytep>=8) {
lmode=OWM_SLEEP;  //all bits processed
break;
}
}
lsrcount=0;
lactbit=(owid[lbytep]&lbitp)==lbitp;
lwmode=lactbit;
}
break;
}
break;
case OWM_MATCH_ROM:
if (p==((owid[lbytep]&lbitp)==lbitp)) {  //Compare with ID Buffer
lbitp=(lbitp<<1); 				if (!lbitp) { 					lbytep++; 					lbitp=1; 					if (lbytep>=8) {
lmode=OWM_READ_COMMAND;  //same? get next command

cbuf=0;
break;
}
}
} else {
lmode=OWM_SLEEP;
}
break;
case OWM_GET_ADRESS:
if (p) { //Get the Address for reading
counterpack.bytes[lbytep]|=lbitp;
}
//address is part of crc
if ((lscrc&1)!=p) lscrc=(lscrc>>1)^0xA001; else lscrc >>=1;
lbitp=(lbitp<<1); 			if (!lbitp) { 				lbytep++; 				lbitp=1; 				if (lbytep==2) { 					lmode=OWM_READ_MEMORY_COUNTER; 					lactbit=(lbitp&counterpack.bytes[lbytep])==lbitp; 					lwmode=lactbit; 					lsrcount=(counterpack.addr&0xfe0)+0x20-counterpack.addr; 					//bytes between start and Counter Values, Iam never understanding why so much??? 					break; 				} else counterpack.bytes[lbytep]=0; 			} 			break; 		case OWM_READ_MEMORY_COUNTER: 			RESET_LOW; 			//CRC16 Calculation 			if ((lscrc&1)!=lactbit) lscrc=(lscrc>>1)^0xA001; else lscrc >>=1;
p=lactbit;
lbitp=(lbitp<<1); 			if (!lbitp) { 				lbytep++; 				lbitp=1; 				if (lbytep==3) { 					lsrcount--; 					if (lsrcount) lbytep--; 					else  {//now copy counter in send buffer 						switch (counterpack.addr&0xFe0) { 						case 0x1E0: 							counterpack.counter=Counter0; 							break; 						case 0x1C0: 							counterpack.counter=Counter1; 							break; 						default: counterpack.counter=0; 						} 					} 				} 				if (lbytep>=13) { //done sending
lmode=OWM_SLEEP;
break;
}
if ((lbytep==11)&&(lbitp==1)) { //Send CRC
counterpack.crc=~lscrc;
}

}
lactbit=(lbitp&counterpack.bytes[lbytep])==lbitp;
lwmode=lactbit;

break;
#ifdef _ONE_DEVICE_CMDS_
case OWM_READ_ROM:
RESET_LOW;
lbitp=(lbitp<<1); 			if (!lbitp) { 				lbytep++; 				lbitp=1; 				if (lbytep>=8) {
lmode=OWM_SLEEP;
break;
}
}
lactbit=(lbitp&owid[lbytep])==lbitp;
lwmode=lactbit;
break;
#endif
}
if (lmode==OWM_SLEEP) {DIS_TIMER;}
if (lmode!=OWM_PRESENCE)  {
TCNT_REG=~(OWT_MIN_RESET-OWT_READLINE);  //OWT_READLINE around OWT_LOWTIME
EN_OWINT;
}
mode=lmode;
wmode=lwmode;
bytep=lbytep;
bitp=lbitp;
srcount=lsrcount;
actbit=lactbit;
scrc=lscrc;
}

PC_INT_ISR  //for counting  defined for specific device

int main(void) {
mode=OWM_SLEEP;
wmode=OWW_NO_WRITE;
OW_DDR&=~OW_PINN;

uint8_t i;
for(i=0;i<sizeof(counterpack);i++) counterpack.bytes[i]=0;
Counter0=0;
Counter1=0;

SET_FALLING;

INIT_AVR
DIS_TIMER;

INIT_COUNTER_PINS

sei();

while(1){

}
}

schemat DS2424Pobierz dokumentację (64KB)

Udostępnij:Share on FacebookEmail this to someoneWykop!Share on Google+Print this pageShare on TumblrTweet about this on Twitter

25 odpowiedzi do “Zamiennik licznika impulsów DS2423 na ATtiny25”

  1. Witam kolegę po fachu.
    Jestem raczej niedzielnym elektronikiem więc trochę trudno mi przekuć schemat płytki w realne urządzenie…Jakieś zdjęcia płytki z układem? Pozdrawiam

  2. Niestety testowałem układ wyłącznie na płytce stykowej, więc nie posiadam wzoru płytki. Obecnie mam dopiero w planach użycie tego układu w praktyce, w stacji meteo.

  3. Witam,
    Czy „to” ruszy na ATtiny2313? Na stronie niby coś piszą, że tak, ale nie bardzo rozumiem o co chodzi.
    Jeżeli tak to gdzie znajdę schemat?
    Z góry dziękuję za pomoc.

  4. Według strony powinno zadziałać. Nie próbowałem.
    W kodzie jest taki fragment
    „//OW_PORT Pin 6 – PB1
    //Analog input PB2”
    czyli prawdopodobnie:
    1wire – portb.1
    input portb.2
    Do tego dochodzi konieczność kompilowania programu na nowo – wygodniej chyba kupić attiny25 i zaprogramować gotowym hexem

  5. Właśnie tak zrobiłem, kupiłem ATtiny25.
    Na dniach będę próbował to wszystko zrobić. Mam nadzieję, że uda się odczytać liczniki: prądu i wody.
    Zastanawia mnie jeszcze taka rzecz, jak zrobić zasilanie awaryjne gdy braknie prądu w domu.

  6. Najprościej chyba użyć jakiegoś małego aku żelowego, doładowywanego gdy zasilanie działa.
    Tylko czy to się opłaca? Braki prądu to kilka chwil rocznie, cała aparatura podtrzymująca to aku, ładowarka, sterownik ładowania – mi by sie nie chciało:)

  7. Witam,
    Próbuję przerobić plik schematu na PCB, ale nie wychodzi mi to.. Może już ktoś ma taki wzór płytki przygotowany? Nie rozumiem do końca czym na schemacie jest element JP1, i jak jest połączony z resztą układu..

  8. JP1 jest standardowym złączem ISP (zwane też ‚Kanda’) do programowania procesora – można go nie uwzględniać w układzie – jeśli procek będzie wcześniej zaprogramowany.

    Wzór płytki znalazłem gdzieś w swoich zasobach Eagle – niestety nie jest on zgodny ze schematem – gdyż posiada dodatkowo miejsce na wzmacniacz LM386 (po prawej stronie) oraz wejścia na czujnik zbliżeniowy TCRT1000. Jest on dostępny w paczce z dokumentacją.

  9. Czym odczytujecie magistrale 1-Wire?
    Ja mam prosty konwerter na diodach (RS-232) i właśnie tak sobie myślę czy uda mi się odczytać ten licznik na ATtiny25?

  10. Ja mam konwerter 1WireRS232 na DS2480B i FT232RL RS232USB. Jak będę miał płytkę zrobioną to tak będę testował układ na ATtiny25.

  11. Kupiłem, producent: mera-projekt model: MP00206 76zł brutto. Tańsza wersja MP00202 56zł. Polecam, działa bez problemów.

  12. u mnie 1wire działa zarówno na własnej produkcji klonie układu mera-projektu, jak i na porcie szeregowym, we współpracy z max232.

    Do ds2480b mogę podrzucić schemat i płytkę.
    Na diodach nie zadziała – ten układ nadaje się wyłącznie do zasilania układów parasite-power (wyłącznie dwużyłowych)

  13. Witam Panie Piotrze piszę w sprawie licznika impulsów emulowanego na attiny25. Mam problem bo na magistrali 1wire jest on wykrywany lecz mam problem ze zliczniem impulsów chodzi mi o wejsca input podciagam je do +5V rezytorem 4,7 k i w momencie zwarcia do masy nie nalicza impulsow (OneWireViewer) Chciałbym użyć tego do liczenia impulsów z licznika bemko, który posiada wyjścia S0+ i S0-

  14. Panie Piotrze,

    Bardzo przydatny artykuł.
    Czy może Pan podzielić się schematem i płytką w Eagle? Będę bardzo wdzięczny.

    Czy mierzeył Pan jaki jest pobór prądu przez układ?

  15. Niestety nie posiadam płytki wyłącznie dla tego układu. Obecnie pracuje on u mnie już tylko w jednym urządzeniu, jako część większej całości.
    Nie mierzyłem również nigdy poboru prądu przez mikroprocesor.

  16. Dla zainteresowanych, układ ds2423 można obecnie kupić na allegro za ok 20zł

  17. Na stronie są niedziałające linki, kod źródłowy przy skopiowaniu i próbie kompilacji krzaczy błędami – w sumie pewnie gdzieś poprzez te udostępnianie na stronie się kaszani bo widzę że na pierwszy rzut oka źródła są te same co na stronie autora. Te ściągnięte od autora (źródła) kopilują się prawidłowo. Liczniki są dwa 32 bitowe (wystarczy podejrzeć źródła programu). Aktywne na zbocze OPADAJĄCE – tak jest w programie. Spokojnie można by dodać obsługę usypiania attiny podczas gdy nic nie robi tym bardziej że napisane jest wszystko na przerwaniach. U mnie działa i zlicza impulsy z licznika energii.

Dodaj komentarz

Twój adres email nie zostanie opublikowany.