O2 Sensor ocs 3rl - continued

Hi, So continuing from:

Maybe this post should replace the old one.

I cant seem to get a value except 0. I built this:

In the documentation there are many scary words, so I assume I am doing something wrong.

Pls help.

The “pulse” (READ) type of the read-bytes node must receive a signal, otherwise the byte will not be read. Each time a pulse arrives at READ, the node reads new values ​​of the byte sent to RX. Try to send a signal from the clock node to the READ input of the read-bytes node, and from its END output to the UPD input of the clear-display node.

What nazarijtipusak080 said is your first problem, but even changing that is going to give you very erratic (and wrong) values.

The sample program indicates that there are 12 bytes of data to read, and you need to combine bytes to get actual readings. ( (4th byte * 256) + (5th byte) ) / 10 = % oxygen
(The example says USART2_RXbuffer[3] for 4th byte because it is 0-based, so 1st byte is [0]). Your sensor is sending the full 12 bytes of data every 1/2 second, so you won’t want to wait a full second to read the bytes. If you don’t care about the other data (humidity, temp, etc.), then you don’t need to save that data, but you will need to perform the reads to get to the data you want.


Ok, I did this but it did not change a thing. The value remains the same. 0
I am really sorry but I don’t know what bytes of data, 4th byte or any of that means.
The only thing practical I understood is (I assume) to change the clock to below 0.5
I tried finding any post or documentation on uart but they are few, assume some knowledge or are outside of xod.

Can someone please give me an example.

Here is my example that I used to test… The shift-count node makes a four-byte word from the received bytes one by one… the micros-to-u32 node allows you to extract each byte from this word separately.This is just an example…You need to adjust to your needs. But it works for me.
example-uart.xodball (10.2 KB)


This is your example. All I did was set the pins. At first it showed 00h,00h,00h,00h
But then out of curiosity i reversed the pins (rewired 9 to 8 and 8 to 9, the wrong way on purpose) and it started to switch very quickly.
Maybe it’s a hardware glitch, frankly at this point I don’t really care anymore, was naive to think it couldn’t be that hard.
Besides It’s doubly my fault because there actually is a premade solution but I though it be nice to have all under one display and not two.

Just wanted people to know.
Thanks all for the help.


This is great!
I am getting something when I wire it the wrong way. Half way there!
I swear I checked a million times if I messed up the wiring.

So in this example there is this wonderful parse tabular node, with index, etc…

BUT that would be too easy!

Nooo, we need to suffer a bit:

So much fun!

But I am sure, as always, I am doing something wrong…
Fortunately i can download the project:

And when I load it OMG, THERE IT IS:

Ofcourse, that’s only if I load that save file. If I load my own it’s gone again.
Now all I have to do is replicate my old tree in the new save file. EXCITING!!!
Hope you all are enjoying my documented adventures just as much as I am.

The sample code you started with reads 12 bytes of data. If you use read-byte, it will only read a single byte. You need to do that 12 times every 1/2 second, so you need 12 read-byte nodes chained together. If you only care about oxygen concentration, then you only care about output from the 4th & 5th read-byte nodes.

The read-bytes node will read all available data, but only return the last byte, which isn’t the information you want. If you have trouble getting consistent results with the 12 read-byte nodes, you might want to use the read-bytes node to drain the input queue, delay 0.5 seconds, then read 12 bytes of data. If you are going to do this every cycle and only care about oxygen concentration, then you only need to read 5 bytes and let the read-bytes node cycle through the rest of the bytes you are ignoring anyway.

I get the theory but that does not help me much, since it is all text and I am left with converting this into something concrete. I am dumb (if it wasn’t obvious by now), I need pictures.
What is a read byte chain?
How do I make one?
How do I define what node is 4th or 5th?

Because this does not help:

All I found is a picture of the good old parse tabular.


It’s in a lot of examples that have to do with uart. So simple. You just select the index and that is your node. But the hard way is more rewarding I guess.

Look, I gave you so many entertaining screen shots. Is it too much to ask for one from you?

I apologize for not answering right away. Since the data is sent from your sensor constantly, there must be a buffer between the shift-count node and the micros-to-u32 node, which is updated once in a certain period of time. As for waiting for the uart: the rx receiver must be connected to the tx transmitter, the tx receiver to the rx transmitter. In my case, I caught four bytes from the transmitter. I’ve tried different options, but accepting a single byte works best. So I just did a sequential reception of four bytes one at a time. Through shift-count I combine four bytes into a word. In my case, I added the buffer later…that’s why it’s not here. I also had an Arduino nano board as a transmitter. After pressing the button, bytes were transferred on it. Shift-count nodes can be connected together and have two, three or more four-byte words… The only thing you really have to think about is the synchronization of the receiver with the transmitter. You can try applying power to the sensor after your board is ready to accept data.


Thanks but I am done with this #$%
Something as simple as reading a value should not be this complicated.
Thank you all for your help but this is simply not worth my time!

I’m sorry you feel that way, but part of this is on you. Serial communication is not trivial & builds on program flow & data structures and other concepts you skipped over while starting on your first project. As the saying goes, it is best to start at the beginning; you tried to jump in near the end. There are other sensors that have analog output that just need an analog-read node to get data from, but for things like air sensors, they often need that data run through a formula that likely includes temperature calculations to make it meaningful. Your sensor does those calculations for you, but needs a more complex method to return more details to you.

I don’t have your hardware to test this, so there could be bugs…

If you look inside the read-bytes node, it uses an is-available node to determine if there is any data to read. Rather than randomly trying to read based on clock ticks, you can use this node to tell you when it is time to read.

You can get your data using individual read-byte nodes, but it might be cleaner using read-bytes. You provided examples of using read-bytes and an accumulator, but the accumulator converts bytes to string & getting it back out as a byte/number is troublesome; I don’t think your example will work correctly. I could probably create a node to return char instead of string, but I already have a queue-buffer node that can create a stack in gweimer/utils library (gweimer/utils — XOD).

is-available has boolean outputs. When boolean changes from false to true, it is read as a pulse on pulse input pins, so we can start with


This will push bytes onto the stack (saving the last 2) until we have pushed 5 values (so we have bytes 4 & 5), then ignore remaining bytes read (gate will block pulses pushing onto stack)

The right queue node will be the older value (byte 4). The data you provided indicates %oxygen is byte4 times 256 plus byte5 divided by 10.


This value will change as data is pushed through the stack, so you want to save it in a buffer that only updates when we have valid data (when count is NOT less-or-equal to 5). We also need to reset count before we start reading (add defer before read so we know count is reset before we read):

Now every time we get new data, we read it and calculate new oxygen level, which is stored in the buffer node.

The only down-side of this type of script is startup or glitch during run may cause is-available to be true without sending a pulse to the following code. This results in data to be read without the program knowing it is time to read. Since we don’t read data, the queue is never cleared, so is-available will never be false again, so it can never change to true to cause a pulse to read data. It will look like your program is hung. The fix for this is to add a watchdog reset. This is something that runs outside your program to force a reset if something goes wrong. The easiest implementation is a timer that runs for longer than your loop (in this case waiting for new data & reading it, so something > 0.5 seconds) and gets restarted every loop so that the delay only completes if the your program does not loop & restart the timer. In this case, we would want the watchdog reset to restart on boot, and each time we read. If the delay completes, then we force a read & restart the timer again.


We have to be careful with this since it could force a read when there is no data to be read (i.e. if sensor was disconnected). In this case, read-bytes will just end without doing any reads because it checks for data being available. Since it doesn’t read any data, it doesn’t change count & buffer doesn’t get updated, so nothing happens & nothing gets broken.

If you want to see how often the watchdog reset is triggered, you can add a count node and display that count in a watch node or on your display showing %oxygen

If you don’t want to deal with accumulators or queue/stacks, it is actually less complicated to just do 5 read-byte nodes to get the data you want, then do a read-bytes to clear out the unused data:


Technically, I want the buffer updated after 5th read-byte (with defer to make sure calculations have run), but it was easier/cleaner just to use the read-bytes-END pin.

I’m not sure what will happen now if the watchdog reset triggers & there is no data to be read…if read-byte blocks until data is available, you should be OK (if getting a 2nd pulse to read data doesn’t cause problems); otherwise you are going to get invalid data. It would probably be safer to add code that prevents watchdog reset from triggering a reset if there is no data to be read… An easier solution might just be to have delay-DONE trigger a read-bytes to clear old data (if any) & let new data trigger your loop when it comes in…

It also looks like I was wrong…I assumed is-available had boolean outputs; it actually has pulse outputs, and pulses every time a check is made, so there would be no need for a watchdog reset in this patch. Rather than run is-available-UPD as a loop, it might be better to pulse it using a clock node so there is time to finish reads before another pulse is started…How long to make the clock ticks will depend on how long it takes to do the reads, which will vary depending on how much other “stuff” is being run at the same time and which micro-controller you are using. I would probably try 1/2 the expected update times to start with, so every 0.25 seconds.

2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.