To mój pierwszy raz z DS18B20. Mam problem z odczytem temperatury z DS18b20. Pierwszy odczyt z układu daje warość 0x0550 czyli defaultowa wartosc po resecie.
Jednak nastepne odczyty dają wartość 0x07FF. WTF?
Poniżej listing. Procek taktowany 16MHz z zewnętrznego oscylatora. (F_CPU zdefiniowane na 16000000)
Kod okrojony, ale nie ma nic wspólnego z one wire.
Linia do której podciągnięty jest DQ z DS-a ma pullupa 5K. Próby podłączenia z zasilaniem pasożytniczym i osobnym dają identyczne wyniki (oprócz odczytu zasilania). Jestem 100% pewny co do podłączenia pinów (aż 3) i co do timingów (odczyt romu i pierwszej temperatury 100% poprawny)
Testy kodu na 2 DS-ach:
odczyt ROMu - works perfect
pierwszy odczyt scratchpada po resecie - [0-8] {0x50, 0x05, 0x4B, 0x46, 0x7F, 0xFF, 0x01, 0x10, 0x2F} temperatura 0x0550 czyli perfect
oczyt scratchpada po pierwszej konwersji temperatury i następne w odstępach 5s - [0-8] {0xFF, 0x07, 0x4B, 0x46, 0x7F, 0xFF, 0x01, 0x10, 0x2F} za każdym razem temperatura 0x07FF !!!
odczyt zasilania READ POWER SUPPLY [B4h] - perfect (wynik 0, czyli zasilanie parasite, 0xFF przy osobnym zasilaniu)
Dodam jeszcze że między konwersją a jakąkolwiek aktywnością na linii onewire mam odstęp 5 sekund.
Skończyły mi się pomysły. Jakieś sugestie?
Jednak nastepne odczyty dają wartość 0x07FF. WTF?
Poniżej listing. Procek taktowany 16MHz z zewnętrznego oscylatora. (F_CPU zdefiniowane na 16000000)
int main () {
uint8_t a=0;
uint8_t sp[9] = {0,0,0,0,0,0,0,0,0};
// podswietlenie LCD
backLightOn();
mcuInit();
lcd_init(LCD_DISP_ON)
for (;;) { /* loop forever */
if ( second >= T0_SEC_VAL ) { // ta czesc kodu wykonuje sie raz na sekunde
second = 0;
(....)
lcd_clrscr();
// to tylko wyswietla na lcd wartosc bufora sp - scratchpad
for (uint8_t x = 0; x < 5; x++) {
lcd_gotoxy(x*3,0);
ultoa(sp[x], buff, 16);
lcd_puts(buff);
}
for (uint8_t x = 0; x < 4; x++) {
lcd_gotoxy(x*3,1);
ultoa(sp[x+5], buff, 16);
lcd_puts(buff);
}
//odczyt temperatury z polecenia w poprzedniej petli
if (a >= 5 ){ // odczyt temperatury co 5 sekund
read_scratchpad(sp);
convert_temp(); //wywolanie nastepnej konwersji, ktoej wynik zostanie odczytany za 5 sekund
a=0;
}
else
a++;
}
}
return 0;
}
uint8_t reset_onewire() {
uint8_t r;
// set D0 to output
owOutput();
owHigh();
owLow();
_delay_us(550);
// set D3 back to input
owInput();
r = (OW_PIN_REG & _BV(OW_BIT));
_delay_us(500);
return r;
}
void write_onewire(uint8_t bit) {
owOutput();
owHigh();
if (bit == 0) {
owLow();
_delay_us(65); // hold low for at least 60us
owHigh();
} else {
owLow();
_delay_us(10); // < 15us for 1 bit
owHigh();
}
owInput();
if (bit == 1)
_delay_us(60); // just to pad out the rest of the slot to >60us
}
uint8_t read_onewire() {
uint8_t result;
// set D3 to output
owOutput();
owHigh();
owLow();
_delay_us(2);
owInput();
_delay_us(10);
result = (OW_PIN_REG & _BV(OW_BIT));
result = result ? 1 : 0; // always return either 1 or 0
_delay_us(60); // make sure the slot is >60us long
return result;
}
void write_onewire_byte(uint8_t command) {
uint8_t i;
cli();
for (i = 0; i < 8; i++) {
write_onewire(command & 1);
command >>= 1;
}
sei();
}
uint8_t read_onewire_byte() {
uint8_t r,i;
cli();
r = 0;
for (i = 0; i < 8; i++) {
r |= (read_onewire() << (i));
}
sei();
return r;
}
void convert_temp() {
reset_onewire();
write_onewire_byte(0xCC); // skip ROM command
write_onewire_byte(0x44); // convert T
}
uint16_t read_temp() {
uint8_t scratchpad[9];
read_scratchpad(scratchpad);
// Just return the temp. in Celcius from the scratchpad.
return ((scratchpad[1] << 8) | scratchpad[0]);
}
void read_scratchpad(uint8_t *scratchpad){
uint8_t i;
for (i = 0; i < 9; i++) scratchpad[i] = 0;
reset_onewire();
write_onewire_byte(0xCC); // skip ROM
write_onewire_byte(0xBE); // read scratchpad (9 bytes)
for (i = 0; i < 9; i++) {
scratchpad[i] = read_onewire_byte();
}
}
inline void owHigh() {
OW_PORT |= _BV(OW_BIT);
}
inline void owLow() {
OW_PORT &= ~_BV(OW_BIT);
}
inline void owInput() {
OW_DDR &= ~_BV(OW_BIT);
}
inline void owOutput() {
OW_DDR |= _BV(OW_BIT);
}
void mcuInit()
{
cli();
//wszystkie porty jako wejscia z pullupami
DDRB = 0;
DDRC = 0;
DDRD = 0;
PORTB = 0xFF;
PORTC = 0xFF;
PORTD = 0xFF;
(...)
sei();
}
Kod okrojony, ale nie ma nic wspólnego z one wire.
Linia do której podciągnięty jest DQ z DS-a ma pullupa 5K. Próby podłączenia z zasilaniem pasożytniczym i osobnym dają identyczne wyniki (oprócz odczytu zasilania). Jestem 100% pewny co do podłączenia pinów (aż 3) i co do timingów (odczyt romu i pierwszej temperatury 100% poprawny)
Testy kodu na 2 DS-ach:
odczyt ROMu - works perfect
pierwszy odczyt scratchpada po resecie - [0-8] {0x50, 0x05, 0x4B, 0x46, 0x7F, 0xFF, 0x01, 0x10, 0x2F} temperatura 0x0550 czyli perfect
oczyt scratchpada po pierwszej konwersji temperatury i następne w odstępach 5s - [0-8] {0xFF, 0x07, 0x4B, 0x46, 0x7F, 0xFF, 0x01, 0x10, 0x2F} za każdym razem temperatura 0x07FF !!!
odczyt zasilania READ POWER SUPPLY [B4h] - perfect (wynik 0, czyli zasilanie parasite, 0xFF przy osobnym zasilaniu)
Dodam jeszcze że między konwersją a jakąkolwiek aktywnością na linii onewire mam odstęp 5 sekund.
Skończyły mi się pomysły. Jakieś sugestie?
