ow: add alarm scans and timing tweaking (#3461)

This commit is contained in:
Johan Ström 2021-09-08 22:34:43 +02:00 committed by Nathaniel Wesley Filardo
parent 98882832d0
commit 21ab6eddc3
4 changed files with 134 additions and 22 deletions

View File

@ -75,6 +75,20 @@ static uint8_t LastFamilyDiscrepancy[NUM_OW];
static uint8_t LastDeviceFlag[NUM_OW];
#endif
struct onewire_timings_s onewire_timings = {
.reset_tx = 480,
.reset_wait = 70,
.reset_rx = 410,
.w_1_low = 5,
.w_1_high = 52,
.w_0_low = 65,
.w_0_high = 5,
.r_low = 5,
.r_wait = 8,
.r_delay = 52
};
void onewire_init(uint8_t pin)
{
// pinMode(pin, INPUT);
@ -108,13 +122,13 @@ uint8_t onewire_reset(uint8_t pin)
noInterrupts();
DIRECT_WRITE_LOW(pin);
interrupts();
delayMicroseconds(480);
delayMicroseconds(onewire_timings.reset_tx);
noInterrupts();
DIRECT_MODE_INPUT(pin); // allow it to float
delayMicroseconds(70);
delayMicroseconds(onewire_timings.reset_wait);
r = !DIRECT_READ(pin);
interrupts();
delayMicroseconds(410);
delayMicroseconds(onewire_timings.reset_rx);
return r;
}
@ -127,7 +141,7 @@ static void onewire_write_bit(uint8_t pin, uint8_t v, uint8_t power)
if (v & 1) {
noInterrupts();
DIRECT_WRITE_LOW(pin);
delayMicroseconds(5);
delayMicroseconds(onewire_timings.w_1_low);
if (power) {
DIRECT_WRITE_HIGH(pin);
} else {
@ -135,18 +149,18 @@ static void onewire_write_bit(uint8_t pin, uint8_t v, uint8_t power)
}
delayMicroseconds(8);
interrupts();
delayMicroseconds(52);
delayMicroseconds(onewire_timings.w_1_high);
} else {
noInterrupts();
DIRECT_WRITE_LOW(pin);
delayMicroseconds(65);
delayMicroseconds(onewire_timings.w_0_low);
if (power) {
DIRECT_WRITE_HIGH(pin);
} else {
DIRECT_MODE_INPUT(pin); // drive output high by the pull-up
}
interrupts();
delayMicroseconds(5);
delayMicroseconds(onewire_timings.w_0_high);
}
}
@ -161,12 +175,12 @@ static uint8_t onewire_read_bit(uint8_t pin)
noInterrupts();
DIRECT_WRITE_LOW(pin);
delayMicroseconds(5);
delayMicroseconds(onewire_timings.r_low);
DIRECT_MODE_INPUT(pin); // let pin float, pull up will raise
delayMicroseconds(8);
delayMicroseconds(onewire_timings.r_wait);
r = DIRECT_READ(pin);
interrupts();
delayMicroseconds(52);
delayMicroseconds(onewire_timings.r_delay);
return r;
}
@ -289,7 +303,7 @@ void onewire_target_search(uint8_t pin, uint8_t family_code)
// Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : device not found, end of search
//
uint8_t onewire_search(uint8_t pin, uint8_t *newAddr)
uint8_t onewire_search(uint8_t pin, uint8_t *newAddr, uint8_t alarm_search)
{
uint8_t id_bit_number;
uint8_t last_zero, rom_byte_number, search_result;
@ -318,7 +332,7 @@ uint8_t onewire_search(uint8_t pin, uint8_t *newAddr)
}
// issue the search command
onewire_write(pin, 0xF0, owDefaultPower);
onewire_write(pin, alarm_search ? 0xEC : 0xF0, owDefaultPower);
// loop to do the search
do

View File

@ -47,6 +47,24 @@
#define DIRECT_WRITE_LOW(pin) (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 0))
#define DIRECT_WRITE_HIGH(pin) (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 1))
// This allows tweaking of individual timings when doing onewire operations
struct onewire_timings_s {
uint16_t reset_tx;
uint16_t reset_wait;
uint16_t reset_rx;
uint8_t w_1_low;
uint8_t w_1_high;
uint8_t w_0_low;
uint8_t w_0_high;
uint8_t r_low;
uint8_t r_wait;
uint8_t r_delay;
};
extern struct onewire_timings_s onewire_timings;
void onewire_init(uint8_t pin);
// Perform a 1-Wire reset cycle. Returns 1 if a device responds
@ -101,7 +119,8 @@ void onewire_target_search(uint8_t pin, uint8_t family_code);
// might be a good idea to check the CRC to make sure you didn't
// get garbage. The order is deterministic. You will always get
// the same devices in the same order.
uint8_t onewire_search(uint8_t pin, uint8_t *newAddr);
// If alarm_search is non-zero, it only looks for devices with the Alarm Flag set (if supported)
uint8_t onewire_search(uint8_t pin, uint8_t *newAddr, uint8_t alarm_search);
#endif
#if ONEWIRE_CRC

View File

@ -201,8 +201,15 @@ static int ow_search( lua_State *L )
luaL_Buffer b;
luaL_buffinit( L, &b );
char *p = luaL_prepbuffer(&b);
uint8_t alarm_search = 0;
if(onewire_search(id, (uint8_t *)p)){
if(lua_isnumber(L, 2))
alarm_search = lua_tointeger(L, 2);
if(alarm_search != 0)
alarm_search = 1;
if(onewire_search(id, (uint8_t *)p, alarm_search)){
luaL_addsize(&b, 8);
luaL_pushresult( &b );
} else {
@ -281,6 +288,33 @@ static int ow_crc16( lua_State *L )
#endif
#endif
// Lua: r = ow.set_timings( reset_tx, reset_wait, reset_rx, w1_low, w1_high, w0_low, w0_high, r_low, r_wait, r_delay )
static int ow_set_timings( lua_State *L )
{
if(lua_isnumber(L, 1))
onewire_timings.reset_tx = lua_tointeger(L, 1);
if(lua_isnumber(L, 2))
onewire_timings.reset_wait = lua_tointeger(L, 2);
if(lua_isnumber(L, 3))
onewire_timings.reset_rx = lua_tointeger(L, 3);
if(lua_isnumber(L, 4))
onewire_timings.w_1_low = lua_tointeger(L, 4);
if(lua_isnumber(L, 5))
onewire_timings.w_1_high = lua_tointeger(L, 5);
if(lua_isnumber(L, 6))
onewire_timings.w_0_low = lua_tointeger(L, 6);
if(lua_isnumber(L, 7))
onewire_timings.w_0_high = lua_tointeger(L, 7);
if(lua_isnumber(L, 8))
onewire_timings.r_low = lua_tointeger(L, 8);
if(lua_isnumber(L, 9))
onewire_timings.r_wait = lua_tointeger(L, 9);
if(lua_isnumber(L, 10))
onewire_timings.r_delay = lua_tointeger(L, 10);
return 0;
}
// Module function map
LROT_BEGIN(ow, NULL, 0)
LROT_FUNCENTRY( setup, ow_setup )
@ -304,6 +338,7 @@ LROT_BEGIN(ow, NULL, 0)
LROT_FUNCENTRY( crc16, ow_crc16 )
#endif
#endif
LROT_FUNCENTRY( set_timings, ow_set_timings )
LROT_END(ow, NULL, 0)

View File

@ -60,14 +60,14 @@ Stops forcing power onto the bus. You only need to do this if you used the 'powe
#### Returns
`nil`
####See also
#### See also
- [ow.write()](#owwrite)
- [ow.write_bytes()](#owwrite_bytes)
## ow.read()
Reads a byte.
####Syntax
#### Syntax
`ow.read(pin)`
#### Parameters
@ -118,10 +118,11 @@ Clears the search state so that it will start from the beginning again.
Looks for the next device.
#### Syntax
`ow.search(pin)`
`ow.search(pin, [alarm_search])`
#### Parameters
`pin` 1~12, I/O index
- `pin` 1~12, I/O index
- `alarm_search` 1 / 0, if 0 a regular 0xF0 search is performed (default if parameter is absent), if 1 a 0xEC ALARM SEARCH is performed.
#### Returns
`rom_code` string with length of 8 upon success. It contains the rom code of slave device. Returns `nil` if search was unsuccessful.
@ -190,7 +191,7 @@ else
end
```
####See also
#### See also
[ow.reset()](#owreset)
## ow.setup()
@ -230,7 +231,7 @@ Sets up the search to find the device type `family_code`. The search itself has
#### Returns
`nil`
####See also
#### See also
[ow.search()](#owsearch)
## ow.write()
@ -247,7 +248,7 @@ Writes a byte. If `power` is 1 then the wire is held high at the end for parasit
#### Returns
`nil`
####See also
#### See also
[ow.depower()](#owdepower)
## ow.write_bytes()
@ -264,5 +265,48 @@ Writes multi bytes. If `power` is 1 then the wire is held high at the end for pa
#### Returns
`nil`
####See also
#### See also
[ow.depower()](#owdepower)
## ow.set_timings()
Tweak different bit timing parameters. Some slow custom devices might not work perfectly well with NodeMCU as 1-wire master. Since NodeMCU ow module is bit-banging the 1-wire protocol, it is possible to adjust the timings a bit.
Note that you can break the protocol totally if you tweak some numbers too much. This should never be needed with normal devices.
#### Syntax
`ow.set_timings(reset_tx, reset_wait, reset_rx, w1_low, w1_high, w0_low, w0_high, r_low, r_wait, r_delay)`
#### Parameters
Each parameter specifies number of microseconds to delay at different stages in the 1-wire bit-banging process.
A nil value will leave the value unmodified.
- `reset_tx` pull bus low during reset (default 480)
- `reset_wait` wait for presence pulse after reset (default 70)
- `reset_rx` delay after presence pulse have been checked (default 410)
- `w1_low` pull bus low during write 1 slot (default 5)
- `w1_high` leave bus high during write 1 slot (default 52)
- `w0_low` pull bus low during write 1 slot (default 65)
- `w0_high` leave bus high during write 1 slot (default 5)
- `r_low` pull bus low during read slot (default 5)
- `r_wait` wait before reading bus level during read slot (default 8)
- `r_delay` delay after reading bus level (default 52)
#### Returns
`nil`
#### Example
```lua
-- Give 300uS longer read/write slots for slow MCU based 1-wire slave
ow.set_timings(
nil, -- reset_tx
nil, -- reset_wait
nil, -- reset_rx
nil, -- w1_low
352, -- w1_high
nil, -- w0_low
305, -- w0_high
nil, -- r_low
nil, -- r_wait
352 -- r_delay
)
```