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 GitHub
parent 9b477e0aae
commit 77e5359087
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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]; static uint8_t LastDeviceFlag[NUM_OW];
#endif #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) void onewire_init(uint8_t pin)
{ {
// pinMode(pin, INPUT); // pinMode(pin, INPUT);
@ -108,13 +122,13 @@ uint8_t onewire_reset(uint8_t pin)
noInterrupts(); noInterrupts();
DIRECT_WRITE_LOW(pin); DIRECT_WRITE_LOW(pin);
interrupts(); interrupts();
delayMicroseconds(480); delayMicroseconds(onewire_timings.reset_tx);
noInterrupts(); noInterrupts();
DIRECT_MODE_INPUT(pin); // allow it to float DIRECT_MODE_INPUT(pin); // allow it to float
delayMicroseconds(70); delayMicroseconds(onewire_timings.reset_wait);
r = !DIRECT_READ(pin); r = !DIRECT_READ(pin);
interrupts(); interrupts();
delayMicroseconds(410); delayMicroseconds(onewire_timings.reset_rx);
return r; return r;
} }
@ -127,7 +141,7 @@ static void onewire_write_bit(uint8_t pin, uint8_t v, uint8_t power)
if (v & 1) { if (v & 1) {
noInterrupts(); noInterrupts();
DIRECT_WRITE_LOW(pin); DIRECT_WRITE_LOW(pin);
delayMicroseconds(5); delayMicroseconds(onewire_timings.w_1_low);
if (power) { if (power) {
DIRECT_WRITE_HIGH(pin); DIRECT_WRITE_HIGH(pin);
} else { } else {
@ -135,18 +149,18 @@ static void onewire_write_bit(uint8_t pin, uint8_t v, uint8_t power)
} }
delayMicroseconds(8); delayMicroseconds(8);
interrupts(); interrupts();
delayMicroseconds(52); delayMicroseconds(onewire_timings.w_1_high);
} else { } else {
noInterrupts(); noInterrupts();
DIRECT_WRITE_LOW(pin); DIRECT_WRITE_LOW(pin);
delayMicroseconds(65); delayMicroseconds(onewire_timings.w_0_low);
if (power) { if (power) {
DIRECT_WRITE_HIGH(pin); DIRECT_WRITE_HIGH(pin);
} else { } else {
DIRECT_MODE_INPUT(pin); // drive output high by the pull-up DIRECT_MODE_INPUT(pin); // drive output high by the pull-up
} }
interrupts(); interrupts();
delayMicroseconds(5); delayMicroseconds(onewire_timings.w_0_high);
} }
} }
@ -161,12 +175,12 @@ static uint8_t onewire_read_bit(uint8_t pin)
noInterrupts(); noInterrupts();
DIRECT_WRITE_LOW(pin); DIRECT_WRITE_LOW(pin);
delayMicroseconds(5); delayMicroseconds(onewire_timings.r_low);
DIRECT_MODE_INPUT(pin); // let pin float, pull up will raise DIRECT_MODE_INPUT(pin); // let pin float, pull up will raise
delayMicroseconds(8); delayMicroseconds(onewire_timings.r_wait);
r = DIRECT_READ(pin); r = DIRECT_READ(pin);
interrupts(); interrupts();
delayMicroseconds(52); delayMicroseconds(onewire_timings.r_delay);
return r; 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 // Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : device not found, end of search // 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 id_bit_number;
uint8_t last_zero, rom_byte_number, search_result; 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 // issue the search command
onewire_write(pin, 0xF0, owDefaultPower); onewire_write(pin, alarm_search ? 0xEC : 0xF0, owDefaultPower);
// loop to do the search // loop to do the search
do 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_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)) #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); void onewire_init(uint8_t pin);
// Perform a 1-Wire reset cycle. Returns 1 if a device responds // 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 // 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 // get garbage. The order is deterministic. You will always get
// the same devices in the same order. // 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 #endif
#if ONEWIRE_CRC #if ONEWIRE_CRC

View File

@ -201,8 +201,15 @@ static int ow_search( lua_State *L )
luaL_Buffer b; luaL_Buffer b;
luaL_buffinit( L, &b ); luaL_buffinit( L, &b );
char *p = luaL_prepbuffer(&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_addsize(&b, 8);
luaL_pushresult( &b ); luaL_pushresult( &b );
} else { } else {
@ -281,6 +288,33 @@ static int ow_crc16( lua_State *L )
#endif #endif
#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 // Module function map
LROT_BEGIN(ow, NULL, 0) LROT_BEGIN(ow, NULL, 0)
LROT_FUNCENTRY( setup, ow_setup ) LROT_FUNCENTRY( setup, ow_setup )
@ -304,6 +338,7 @@ LROT_BEGIN(ow, NULL, 0)
LROT_FUNCENTRY( crc16, ow_crc16 ) LROT_FUNCENTRY( crc16, ow_crc16 )
#endif #endif
#endif #endif
LROT_FUNCENTRY( set_timings, ow_set_timings )
LROT_END(ow, NULL, 0) LROT_END(ow, NULL, 0)

View File

@ -118,10 +118,11 @@ Clears the search state so that it will start from the beginning again.
Looks for the next device. Looks for the next device.
#### Syntax #### Syntax
`ow.search(pin)` `ow.search(pin, [alarm_search])`
#### Parameters #### 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 #### Returns
`rom_code` string with length of 8 upon success. It contains the rom code of slave device. Returns `nil` if search was unsuccessful. `rom_code` string with length of 8 upon success. It contains the rom code of slave device. Returns `nil` if search was unsuccessful.
@ -266,3 +267,46 @@ Writes multi bytes. If `power` is 1 then the wire is held high at the end for pa
#### See also #### See also
[ow.depower()](#owdepower) [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
)
```