Closed mr-miky closed 1 year ago
PIO driver
You may create up to 8 different OneWireNg
objects derived from OneWireNg_PicoRP2040PIO
driver. To do this you need:
CONFIG_RP2040_PIOSM_NUM_USED
to 1
in OneWireNg_Config.h
(or use appropriate define for this param in you building env).OneWireNg
objects as follows:
static OneWireNg *ow1, *ow2, *ow3, *ow4, *ow5, *ow6, *ow7, *ow8;
...
// create SMs for 1st PIO for 4 distinct pins ow1 = new OneWireNg_PicoRP2040PIO(SOME_PIN1, PULLUP_CONF, 0); ow2 = new OneWireNg_PicoRP2040PIO(SOME_PIN2, PULLUP_CONF, ow1); ow3 = new OneWireNg_PicoRP2040PIO(SOME_PIN3, PULLUP_CONF, ow1); ow4 = new OneWireNg_PicoRP2040PIO(SOME_PIN4, PULLUP_CONF, *ow1);
// create SMs for 2nd PIO for 4 distinct pins ow5 = new OneWireNg_PicoRP2040PIO(SOME_PIN5, PULLUP_CONF, 1); ow6 = new OneWireNg_PicoRP2040PIO(SOME_PIN6, PULLUP_CONF, ow5); ow7 = new OneWireNg_PicoRP2040PIO(SOME_PIN7, PULLUP_CONF, ow5); ow8 = new OneWireNg_PicoRP2040PIO(SOME_PIN8, PULLUP_CONF, *ow5);
NOTE 1: I don't recommend to create `OneWireNg` objects on the static level, since these objects are created at the very initial stage of the program execution and may not always work as you expected. Allocate them using `new` operator by dynamic or in-place memory allocation (see the README for details).
NOTE 2: In this example I'm using directly specified driver `OneWireNg_PicoRP2040PIO` not `OneWireNg_CurrentPlatform`, since the constructors used here are PIO specific.
NOTE 3: If `CONFIG_RP2040_PIOSM_NUM_USED` is set to `2` (the default value) you may create only 2 SMs per PIO, so 4 SMs max. I've observed some minor timings issues if `CONFIG_RP2040_PIOSM_NUM_USED` is `1`, but I believe it shouldn't be an issue for you. Set `1` and give it a try.
**Bit-banging driver**
I don't see a reason for the limit of `OneWireNg` objects created in this case. Make sure to call these objects in a serial order (1st, next 2nd, next 3rd and so on) ~or use mutexes to assure serialization if you call them in threads. `interrupts()` is not re-entrant and it's the reason of problems I guess.~
BTW: You may try to play with `CONFIG_BITBANG_TIMING` param in `OneWireNg_Config.h` and set it to `TIMING_RELAXED` or even `TIMING_NULL` and check results.
EDIT: I've just checked bit-banging driver working on 6 different pins 13-18 for 6 `OneWireNg` objects. No issues observed.
EDIT 2: The re-entrance in multi-threads environment shouldn't be the issue neither. You don't need to use mutexes for this case, since by blocking interrupts threads scheduling will be effectively disabled for a single core and `interrupt()` re-entrance will not occur.
no way...
static OneWireNg_PicoRP2040PIO *homeWires[] = {nullptr, nullptr, nullptr, nullptr};
...
void setupOneWire() {
homeWires[KITCHEN] = new OneWireNg_PicoRP2040PIO(KITCHEN_PIN, false, 0);
homeWires[BEDROOM] = new OneWireNg_PicoRP2040PIO(BEDROOM_PIN, false, *homeWires[KITCHEN]);
homeWires[LIVINGROOM] = new OneWireNg_PicoRP2040PIO(LIVINGROOM_PIN, false, *homeWires[KITCHEN]);
homeWires[BATHROOM] = new OneWireNg_PicoRP2040PIO(BATHROOM_PIN, false, *homeWires[KITCHEN]);
}
void findDevs() {
OneWireNg::Id id;
OneWireNg::Id tempSensor[4] = { };
for (uint8_t i = 0; i < 4; i++) {
if (homeWires[i] != nullptr) {
Sprint("Searching for DS18S20 on bus : %d\n", i);
homeWires[i]->searchFilterAdd(DS18S20);
homeWires[i]->searchFilterAdd(DS2408);
homeWires[i]->searchReset();
while (homeWires[i]->search(id) == OneWireNg::EC_MORE) {
if (*tempSensor[i] != DS18S20)
memcpy(&tempSensor[i], &id[0], sizeof(OneWireNg::Id));
printId(id);
Serial.println("----------");
}
}
else
Sprint("Uninitialized bus %d\n", i);
}
}
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(100);
}
pinMode(LED_BUILTIN, OUTPUT);
...
setupOneWire();
findDevs();
wait = millis();
}
Nothing has changed at all.
In setup() when I run setupOneWire(); hangs and does not run findDevs();
The only way to make it run findDevs(); and then loop(); is to limit it to 2 new OneWireNg_PicoRP2040PIO(......
void setupOneWire() {
homeWires[KITCHEN] = new OneWireNg_PicoRP2040PIO(KITCHEN_PIN, false, 0);
// homeWires[BEDROOM] = new OneWireNg_PicoRP2040PIO(BEDROOM_PIN, false, *homeWires[KITCHEN]);
homeWires[LIVINGROOM] = new OneWireNg_PicoRP2040PIO(LIVINGROOM_PIN, false, *homeWires[KITCHEN]);
// homeWires[BATHROOM] = new OneWireNg_PicoRP2040PIO(BATHROOM_PIN, false, *homeWires[KITCHEN]);
}
and result is :
Searching for DS18S20 on bus : 0
Uninitialized bus 1
Searching for DS18S20 on bus : 2
10:36:A3:6E:0:8:0:2A
----------
10:6E:BC:6E:0:8:0:B6
----------
10:1E:A2:48:0:8:0:89
----------
10:D5:80:6E:0:8:0:EC
----------
Uninitialized bus 3
N.B. KITCHEN aka bus 0 is disconnected...
oh noooo i forgot to change -DCONFIG_RP2040_PIOSM_NUM_USED=2 in the compile command
I must absolutely go to sleep !
With the above usage you MUST set CONFIG_RP2040_PIOSM_NUM_USED
to 1
since you are using 4 SMs on the same PIO.
oh noooo i forgot to change -DCONFIG_RP2040_PIOSM_NUM_USED=2 in the compile command
I meant I forgot to change it to 1 , it had always been set to 2 in all tests :-(
Ok, so I assume it's working now.
PIO mode now seems to work with short links, tomorrow I try with 20m links.
What puzzles me is the Bit-Banging mode and the noInterrupts()/interrupts() issue. Tomorrow if I have time I investigate with the debugger to understand why delayUs() enters coma to the third sequence of
noInterrupts(); delayUs(xxx); interrupts();
for example in the reset() function of the old oneWire library. NB. the same code compiled for STM32 and atmega328p is no problem
I am using an RP2040 with arduino pico sdk (not MBED). The problem is that if I use oneWireNg (PIO version) I can’t instantiate more than 2 onewire connections. If I try to use more than 2 of them the RP2040 hangs even before entering setup().
in this way the RP2040 works
in this hangs
I also tried to use the bitbanging mode and in this mode I can instantiate 4 connections but then it hangs when I try to reset the 1-wire bus. This last problem is also present in OneWire not ng and is caused by the use of noInterrupts() and interrupts() before and after delayUs().
The only way I can use the bitbanging version is to comment out noInterrupt() and interrupts() in Platform_Time_Critical.h
Also in the old version of oneWire, if I want it to work, I have to comment out most of the noInterrupts() and interrupts().