PaulStoffregen / OneWire

Library for Dallas/Maxim 1-Wire Chips
http://www.pjrc.com/teensy/td_libs_OneWire.html
579 stars 382 forks source link

ATmega328pb does not wake up on pin change after reading a point #137

Open zaplakkies opened 2 months ago

zaplakkies commented 2 months ago

Description

Im having a problem where if I read an id point, which reads fine btw, after the unit goes to sleep it wont wake up. If I short the line to wake up the unit it tries to find a point and when it fails it goes to sleep. ie the wakeup from sleep works fine as long as I don't read a point successfully.

Steps To Reproduce Problem

using an atmega328pb put an led on pin25 and the dallas line with the appropriate pull up resistor on pin32 (INT0). Use the code below. shorting the line wakes the unit up momentarily and then it goes to sleep. This can be done multiple times without problem. Put a DS1990 on the line and it will read the point, then go to sleep. Now you cannot wake the unit up

Hardware & Software

Board: Custom board with the bare minimum using an atmega328pb Shields / modules used : none Arduino IDE version : not using arduino ide using VScode Version info & package name (from Tools > Boards > Board Manager): 2.3.7 Operating system & version: Linux Ubuntu 23.04

Arduino Sketch

include

include <avr/io.h>

include <avr/sleep.h>

include <avr/interrupt.h>

include

include <avr/power.h>

include <avr/wdt.h>

include

define LED 16 // pin25

define TPout 2 // pin32

byte addr[8]; byte rty; boolean issame; boolean shorted = false;

OneWire ds(2);

volatile bool wokeUp = false;

//// Sleep sections //// void wakeUpInterrupt() { wokeUp = true; } void sleepNow() { set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Choose the lowest power mode

sleep_enable(); sei(); // Enable interrupts to wake up from sleep digitalWrite(LED, LOW); // Enter sleep mode sleep_cpu(); // The program will continue from here when the microcontroller wakes up sleep_disable(); }

void setup() { // initialize digital pin LED_BUILTIN as an output. Serial.begin(9600); // init the leds to be off pinMode(LED, OUTPUT); pinMode(TPout, INPUT); digitalWrite(LED, LOW);

attachInterrupt(digitalPinToInterrupt(TPout), wakeUpInterrupt, CHANGE); Serial.println("end of setup"); sleepNow(); }

void loop() { if (wokeUp) { Serial.println("start of loop"); rty = 10; while (rty != 0) { // start retry loop rty--; pinMode(TPout, INPUT); delay(10); ds.reset_search(); if (ds.search(addr)) { digitalWrite(LED, HIGH); Serial.print("Recorded point, "); Serial.print(addr[3],HEX); Serial.print(addr[2],HEX); Serial.println(addr[1],HEX); delay(100); rty = 0; } } wokeUp = false; Serial.println("end of loop"); delay(100); sleepNow(); }

}

zaplakkies commented 2 months ago

Ive had it a few times where it would just crash directly after reading a point as well. This made me look at the filter caps, which were not a problem. Then I took a look at the library in a bit more detail. After I replaced the two lines in write_bit from DIRECT_WRITE_HIGH(reg, mask); to DIRECT_MODE_INPUT(reg, mask); all problems seem to have vanished. Making it an input automatically makes it high without the risk of shorting the output pin from vcc to gnd. It does not make too much sense as I cant the the ds1990 pulling the line low when the master is pulling it high. It does seem to work though so there is that.