Author Topic: Sensor digital signal with optocoupler  (Read 1988 times)

0 Members and 2 Guests are viewing this topic.

Offline n4teTopic starter

  • Regular Contributor
  • *
  • Posts: 56
  • Country: pr
Sensor digital signal with optocoupler
« on: August 06, 2023, 03:46:35 pm »
I've built a time-of-flight sensor that turns on an optocoupler when the beam is broken. That closes a 24V circuit over long wires (one twisted pair in 100' ethernet routed indoors, 23AWG, 79ohm/km, 90pF/100m), turning on another optocoupler (10mA) connected to an ESP32.

This works great, but I've since decided I want more than a binary signal. I want to send 4 different signals plus none, so 5 unique values. That could be sent in 3 bits.

I've never blinked my own protocol over optocouplers before. Any tips would be appreciated! Is it as simple as just blinking the 3 bits when the beam is broken?

Should I use some framing around the data? Maybe go high for a while before the data to reduce the chance of noise being seen as data? If that is a good idea, roughly how long is sufficient?

Sending 3 bits adds some time to the communication. To keep the sensor responsive I'd guess it should take 100ms max, with less being better. If I go high for 3 cycles and then send 3 bits, 16ms per cycle * 6 = 96ms. Maybe 10ms/cycle is sufficient? Go high for 2 cycles instead of 3? Then 10ms * 5 = 50ms. 10ms/cycle is probably a long time as far as digital signals go, but I'm a little worried about noise and reflections since this isn't a proper transmission line. I hope the optocouplers are sufficient for filtering any noise.

I suppose it would be easiest to send the initial data, then keep it high until the beam is no longer broken. The MCU and sensors are powered from the same source, so the MCU will never come online in the middle of a transmission. After seeing the data the MCU would consider the beam broken until it sees low for more than a few cycles. Good plan?
« Last Edit: August 06, 2023, 03:54:59 pm by n4te »
 

Offline ledtester

  • Super Contributor
  • ***
  • Posts: 3168
  • Country: us
Re: Sensor digital signal with optocoupler
« Reply #1 on: August 06, 2023, 04:53:54 pm »
I would use a serial protocol at a standard baud rate -- easy to generate and easy to decode.

What optocoupler are you using? Here is a serial test of some commonly used optocouplers:

https://github.com/pepaslabs/Electronics/wiki/Designing-a-TTL-Serial-Opto-isolator

Note that they have no trouble transmitting at 9600 baud. Of course you have the 100 feet of twisted pair to worry about -- I would just test it, it probably will just work.
 

Offline Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 3641
  • Country: nl
Re: Sensor digital signal with optocoupler
« Reply #2 on: August 06, 2023, 05:11:10 pm »
It's not clear to me on which side of the cable you want to put the microcontroller, and why you are using opto couplers in the first place.

To me the logical choice would be to use a local microcontroller for each sensor node and let them communicate with each other over RS485. A Twisted pair from a CAT-5 cable is near ideal for RS485, and a wire pair can handle about 1A of current, but you do have a significant voltage drop. Solution is to use a higher voltage (for example 24V) and local SMPS circuits (which also reduce the current through the cable by a factor of almost 5.
 

Offline n4teTopic starter

  • Regular Contributor
  • *
  • Posts: 56
  • Country: pr
Re: Sensor digital signal with optocoupler
« Reply #3 on: August 06, 2023, 05:28:25 pm »
@ledtester Nice link, thanks! In the past I've done UART via RS-485 with optocoupler isolation, using LTV-816S. I tested that with an oscilloscope  up to 128k baud. It actually worked at that speed but the waveform didn't look great. I only needed 9600 baud though, and that looked very nice and has worked great.

My optocoupler for this sensor is a different one though: IL2-X009T. At 9600 baud it'd be 104us bit time. I'm thinking 5-10ms would be fine and possibly more reliable.

Serial at a lower baud rate is a good idea, but for this project I have 8 sensors going into input pins of one ESP32. ESP32 has only 2 usable UARTs so I think I'll need to decode manually.

Quote
It's not clear to me on which side of the cable you want to put the microcontroller, and why you are using opto couplers in the first place.
@Doctorandus_P Sorry, I should have explained more fully. The whole setup goes:
Code: [Select]
ToF sensor > STM32 > optocoupler1 > 24V over long wires > optocoupler2 > ESP32
The optocouplers are 1) so I can use 24V, and 2) so I don't expose the MCUs to the long wires. The communication direction is one way, from the sensor to the ESP32.

Quote
To me the logical choice would be to use a local microcontroller for each sensor node and let them communicate with each other over RS485.

I agree and I did go that route for other things. For this one I thought I'd only need a binary, one way signal, so I tried to keep it simple. Naturally that has bitten me! It's still one way, but needs 5 signals instead of binary. Now I hope to make it work using my existing boards (optocouplers, ESP32 input pin).
 

Offline ledtester

  • Super Contributor
  • ***
  • Posts: 3168
  • Country: us
Re: Sensor digital signal with optocoupler
« Reply #4 on: August 06, 2023, 05:47:39 pm »

Serial at a lower baud rate is a good idea, but for this project I have 8 sensors going into input pins of one ESP32. ESP32 has only 2 usable UARTs so I think I'll need to decode manually.


With a serial protocol you can take advantage of pre-written "software serial" libraries such as this one:

https://github.com/plerup/espsoftwareserial

 

Offline n4teTopic starter

  • Regular Contributor
  • *
  • Posts: 56
  • Country: pr
Re: Sensor digital signal with optocoupler
« Reply #5 on: August 06, 2023, 06:16:09 pm »
Software serial does seem a pretty good solution, thanks! Saves me the trouble (and bugs) of interrupts/etc manually.

I'll have to figure out how to do the sending on the STM32F411CE side. My output pin is PB3, which unfortunately isn't connected to a UART peripheral as TX (it is `UART1_RX`). Seems there's no remapping possible with this MCU, so I'll have to bit bang it or find a software serial library (using STM32CubeIDE).
« Last Edit: August 06, 2023, 06:22:05 pm by n4te »
 

Offline Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 3641
  • Country: nl
Re: Sensor digital signal with optocoupler
« Reply #6 on: August 06, 2023, 10:20:24 pm »
From the way I see it, there is no need for optocouplers at all.
I once designed a PCB with:
* Ethernet connectors.
* SMPS: 24V -> 5V
* uC (atmega 8 or 328 in qfp)
* Programming connector (I do not do "arduino")
* Some small experimentation area.
* RS485 transceivers.

Over the years I've also spent quite some time into debugging my library.
It's now a multi drop network (with 16 bit address space) and all uart stuff is ISR driven.

To me, using that PCB with it's power and network interface is the first thing to go for any uC project, and I have got about 15 nodes running for 15+ years.
And all nodes communicate over the same twisted wire pair. That is what RS485 is for.
But I do admit that I did have spurious resets on some of the nodes, long cables both pick up and transmit noise. And I solved it by putting ferrite cores around some of the CAT-5 cables, and this works quite good, but it's still pending for a more permanent solution. The next iteration of the PCB is going to have better inherent filtering (and probably also an STM32).

Just had a look at the datasheet for the LTV816:
https://media.digikey.com/pdf/Data%20Sheets/Lite-On%20PDFs/LTV-816_826_846.pdf

(Quite atrocious, basic info about properties is way down in the datasheet, below multiple pages of package and tape information. Someone should go and flog them. Yuch!)

It has a response time of 18us, and this is quite typical for a generic optocoupler, but it is too slow for 115k2. Optocouplers like the 6n136 are much faster and it is rated for a transfer rate of 1Mbps, and the price difference is also small.


 

Offline n4teTopic starter

  • Regular Contributor
  • *
  • Posts: 56
  • Country: pr
Re: Sensor digital signal with optocoupler
« Reply #7 on: August 06, 2023, 11:19:19 pm »
The optocouplers isolate my MCUs from each other and from noise/transients in the long wires. Whether that's required may be questionable depending on the environment and other factors, but it's generally a good thing.

RS-485 is great but uses a common GND. When I use RS-485, I still use optocouplers for isolation. I prefer my MCUs to be self contained.

SMPS are also great. I like the Traco TSR 1 series.

Quote
It has a response time of 18us, and this is quite typical for a generic optocoupler, but it is too slow for 115k2.

18us max and 3us typical, but yeah it's not super fast. It worked well for 9600 baud and probably would work fine up to ~57.6k or so. CTR is average at 50-600%. Too bad they don't bin those sweet 600% parts, so I have to treat them as 50% in my designs.

Quote
Optocouplers like the 6n136 are much faster and it is rated for a transfer rate of 1Mbps, and the price difference is also small.

That one is indeed nice and fast. Isolation is lower than most (1k vs 5k V/us). It's fast at 0.2-1.5us but the CTR is atrocious at 5-19%. Considering temp and lifetime degradation, planning for half the minimum CTR is reasonable, so this isn't usable if there is even a little current. That's the tradeoff for high speeds though.

Check out IL2-X009T (and ILD2-X009T and ILQ2-X009T, which they do bin). Those are still pretty fast at 2.3us typical (why is max not published?) and the CTR is 100-500%. My signalling is at 10mA. It annoys me that the single version has 6 legs, making it take up a lot of space.

My sending code is looking like this (STM32 APIs are so clunky):

Code: [Select]
// Inverted, even parity, 1 stop bit, 200 baud.
void send (uint8_t value) {
HAL_TIM_Base_Start(&htim3);
HAL_GPIO_WritePin(SIG_GPIO_Port, SIG_Pin, GPIO_PIN_SET);
delayMicros(5000);
uint8_t i = 7, parity = 0;
while (true) {
uint8_t bit = value & 0x01;
HAL_GPIO_WritePin(SIG_GPIO_Port, SIG_Pin, value & 0x01 ? GPIO_PIN_RESET : GPIO_PIN_SET);
delayMicros(5000);
parity ^= bit;
if (i == 0) break;
i--;
value >>= 1;
}
HAL_GPIO_WritePin(SIG_GPIO_Port, SIG_Pin, parity ? GPIO_PIN_RESET : GPIO_PIN_SET);
delayMicros(5000);
HAL_GPIO_WritePin(SIG_GPIO_Port, SIG_Pin, GPIO_PIN_RESET);
delayMicros(5000);
HAL_TIM_Base_Stop(&htim3);
}

I'll check the timings with a scope and adjust the 5ms delays to come closer to 200 baud.

I think I'll write the receiving code rather than use a library, that way I can send the data then leave the signal high until the ToF beam is no longer broken.
« Last Edit: August 06, 2023, 11:40:53 pm by n4te »
 

Offline Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 3641
  • Country: nl
Re: Sensor digital signal with optocoupler
« Reply #8 on: August 07, 2023, 01:10:26 am »
So you do know your stuff.
6n136 is just an example of an oldie. I think it's from 50+ years ago.
The higher speed optocouplers tend to have internal buffers and amplifiers, so CTR is much less important than with "standard" optocouplers.

Are you aware of the "ADUM" signal isolators?
They work with a capacitive barrier, can have multiple data stream in one IC, and can even have integrated isolated SMPS, so one chip does both power and data (in two directions).
Similar chips are the "ISO" range from Ti, for example ISO1410DW
(Hmm, didn't Ti buy Analog Devices)
I think this started with MOSfet gate drivers. MOSfet gate drivers for half bridges have existed for quite a long time, and these often have built in isolation barrier. But it may also be the other way around, maybe the logic signal isolators were first.

There are also different technologies used. Some are capacitive, others inductive, and there are also based on Hall effect or GMR. Take for example the ACS712 Hall effect current sensor. By arranging the parts on the chip a bit differently, something similar can be used for data transmission.

My sending code is looking like this (STM32 APIs are so clunky):
Yeah, I'm stuggling with that too.
I stopped with bit banging RS232 long ago though.
uC's with multiple UARTS are just too common and cheap to bother with the manual bit fiddling.
Just fill a buffer, start the thing and let an ISR do the rest while the uC is doing something more useful.
(Heck, even sleeping is more useful than bit twiddling in a delay loop).

Also, STM32 is quick enough to handle 9600 ISR/s so you can set a timer and shift out a bit each ISR. That would at least make your timing more consistent.
« Last Edit: August 07, 2023, 01:20:57 am by Doctorandus_P »
 

Offline Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 3641
  • Country: nl
Re: Sensor digital signal with optocoupler
« Reply #9 on: August 07, 2023, 01:27:33 am »
Think a bit about this pseudo code:

Code: [Select]
for( uint8_t bit = 1; bit; bit<<1) {
    if(bit & data){
        output_high();
        parity ^= 1;
    } else {
        output_low();
    }
    delay( BIT_TIME);
}
 

Offline Smokey

  • Super Contributor
  • ***
  • Posts: 2742
  • Country: us
  • Not An Expert
Re: Sensor digital signal with optocoupler
« Reply #10 on: August 07, 2023, 01:50:25 am »
Not sure how many of these you plan on making.  Even if it's a lot, this one part might be cheaper than all that other stuff:

https://www.ti.com/isolation/isolated-interfaces/rs-485-transceivers/overview.html
 

Offline PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 1736
  • Country: au
Re: Sensor digital signal with optocoupler
« Reply #11 on: August 07, 2023, 02:24:46 am »
I've built a time-of-flight sensor that turns on an optocoupler when the beam is broken.
That closes a 24V circuit over long wires (one twisted pair in 100' ethernet routed indoors, 23AWG, 79ohm/km, 90pF/100m), turning on another optocoupler (10mA) connected to an ESP32.

This works great, but I've since decided I want more than a binary signal. I want to send 4 different signals plus none, so 5 unique values. That could be sent in 3 bits.
....
Serial at a lower baud rate is a good idea, but for this project I have 8 sensors going into input pins of one ESP32. ESP32 has only 2 usable UARTs so I think I'll need to decode manually.

That's a little unclear ?
Do you have 8 remote units, and you need to send 5 unique values from each one ?
That needs a multi-drop design, tho your baud rate can be very low.

You could also look at LIN BUS, which is designed for lower speed, lighter payloads.

A Ring bus allows multiple nodes, in a simple location-is-address basis.
An OR wired bus, then needs some address per node, and you can poll to get status replies.

 

Offline n4teTopic starter

  • Regular Contributor
  • *
  • Posts: 56
  • Country: pr
Re: Sensor digital signal with optocoupler
« Reply #12 on: August 07, 2023, 03:08:08 am »
Quote
Are you aware of the "ADUM" signal isolators?

Haven't heard of it, looks interesting. The one I peeked at can handle 100mA on each of 4 channels. I'll read up on it some more, thanks!

Quote
Also, STM32 is quick enough to handle 9600 ISR/s so you can set a timer and shift out a bit each ISR. That would at least make your timing more consistent.

I like that idea, cheers! I only need 200 baud for this.

Quote
Think a bit about this pseudo code:

Nice, yours is a teeny bit better since you use the branch to avoid work.

Quote
Not sure how many of these you plan on making.  Even if it's a lot, this one part might be cheaper than all that other stuff:

8 sensors plus the board they connect to. They are already made, so I'm trying to make that work. A proper transmission line would definitely be better, but I'd need to remake them and it'd take 16 RS-485 transceivers -- one in each sensor and 8 on the main board. I'll do that if a software solution ends up failing. It'd be better but not cheaper, eg MAX14787E is so $90 just in transceivers. Not a big deal though for a one time cost.

Quote
Do you have 8 remote units, and you need to send 5 unique values from each one ?

8 remote units, but each is home run to a single ESP32. I need to send 5 unique values from each one. The devices already exist, so I hope to solve it with software. Each sensor can send a signal (through optocouplers via 24V, 10mA) to an ESP32 input pin, so I'm going to try software UART over that at 200 baud.
 

Offline PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 1736
  • Country: au
Re: Sensor digital signal with optocoupler
« Reply #13 on: August 07, 2023, 03:46:19 am »
Quote
Do you have 8 remote units, and you need to send 5 unique values from each one ?

8 remote units, but each is home run to a single ESP32. I need to send 5 unique values from each one. The devices already exist, so I hope to solve it with software. Each sensor can send a signal (through optocouplers via 24V, 10mA) to an ESP32 input pin, so I'm going to try software UART over that at 200 baud.
Low baud rates should be fine. You can poll at 4-5x faster than the bit time, and run simple state engines for each channel.

I did notice that newer USB-UARTS have lower slowest speeds, which might make testing this easier, as you can test generate and RX using a standard product.

eg CH343 / CH9102 claim to be settable down to 50bps
PL2303GS claims 1 bps to 12 Mbps   8)


Addit : If you want just 5 unique values, you can simplify the interrupt sampling code to measure pulse width low, rather than extract individual bits
Pulse width capture will capture 8 unique values from a sampled pin, driven by a standard UART waveform.

Code: [Select]
// Interrupt at say 1.25ms rate, for 4 counts per bit at 200 baud, and duplicate this code 8x for 8 channels.
 if (Rx_0==0)
    Tim_0++;          // Increment at INT rate while LOW = pulse width capture  ==\___/===
 else // RX = 1   
  if (Tim_0 > PW_min) // can use 2-3 as min width noise filter
    Capt_0 = Tim_0;   // grab pulse width
  endif
  Tim_0 = 0;          // reset ready for next LOW pulse
 endif 
« Last Edit: August 07, 2023, 07:56:52 am by PCB.Wiz »
 

Offline Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 3641
  • Country: nl
Re: Sensor digital signal with optocoupler
« Reply #14 on: August 07, 2023, 07:36:51 am »
A proper transmission line would definitely be better, but I'd need to remake them and it'd take 16 RS-485 transceivers -- one in each sensor and 8 on the main board.

That is not the way RS485 is supposed to work.

Normally you only need 9 devices. One for each node (that is 8) and the ninth is for the "master", and then you daisy chain all the nodes on a single cable.

I'm also weary of Maxim chips. They have a reputation of making quite nice specialized chips, and after a bunch of years they get progressively more expensive and get obsoleted. I am more for buying more standard chips that are interchangeable between different manufacturers. RS485 transceivers have a quite common pinout (in the 8-pin chips), but there are still two variants "Full duplex" (which you selected) and "Half duplex" (where a single wire pair is switched between send and receive)

The Maxim chip is also quite expensive.
If you go to:  Digikey / Product Index / Integrated Circuits (ICs) / Interface / Drivers, Receivers, Transceivers and then filter for "RS485" and then sort on price, the "Union Semiconductor" UM3483EESA comes out on top and it costs 88ct. (Moq 2pcs).
https://www.digikey.com/en/products/detail/union-semiconductor-international-limited/UM3483EESA/13926072

If you are interested in this, have a look at Modbus  RTU. It's a fairly old, but standardized and open bus protocol and it's still popular. Because of it's openness and ease of implementation it's used from industrial to hobby uses. There are plenty of "arduino" level libraries available.

Another good option is to use CAN. Most STM32 have an onboard CAN controller, and it looks like ESP32 also has CAN hardware. Result is, you write your data to some buffer, and then give the CAN hardware in your uC an order to do it's thing while you wait or go do something else. CAN is a quite sophisticated protocol. It's main disadvantage is a quite small packet size of 8 data bytes per packet.

CAN is basically a wired or connection. The (twisted pair) bus wires are pulled together by the cable termination resistors (termination resistors always work on the cable, not on the nodes!) and this is called the "passive" state. When a CAN node sends a "1" bit, it pulls the wires apart. One to GND, and one to it's power supply (usually 5V, but can be 3V3) and this is called the "active" state.

If you want to make your bus really robust, then you can add extra bipolar TVS diodes between the bus wires and GND, and also add PPTC resistors in series with the bus (and possibly power) wires. The TVS diodes diodes give extra ESD protection (also helped by the cold resistance of the PPTC's.) and the combination with the PPTC also protect your circuit against gross wiring faults, such as setting a 24Vdc voltage on the bus wires. In this case the TVS diodes clamp the voltage to a level that nothing gets damaged, and the PPTC devices limit the current to a safe value, so your TVS diodes do not overheat and die after a short while (seconds).

And I still don't completely understand your use of optocouplers. How do you power your remote nodes? I guess it's from the same long cable. Do you also use isolated SMPS modules for this, or are the ground pins of your uC's connected to the GND of your wiring?
Both CAN and RS485 have special feature to handle this. Their "common mode" goes from (about) -7V to +12V (which is 7V above it's 5V power supply) The negative common mode voltage is important and it goes like this:
Suppose you have a long cable with daisy chained nodes, and the cable receives 24Vdc power on the left side. All the nodes draw a bit of current, and the cable is so long and it's resistance so high that it has 3V loss over each power conductor. That means (measured from the power supply, that the power on the "right side" of the cable is 24-3=21V, and the GND at the far right side is 0+3 = 3V.
So if the leftmost node sends a packet of data (0V and 5V signalling) to the rightmost node, then the rightmost node receives data between -3 and +2V. If data is sent from right to left, then the leftmost node receives it as a 3V to 8V data signal. Both of these situations are perfectly fine for both RS485 and CAN. The transceivers are explicitly designed to handle this.

A good Application note for RS485 is "10 ways to bulletproof RS485"
https://www.ti.com/lit/an/snla049b/snla049b.pdf
 

Offline n4teTopic starter

  • Regular Contributor
  • *
  • Posts: 56
  • Country: pr
Re: Sensor digital signal with optocoupler
« Reply #15 on: August 13, 2023, 05:31:39 pm »
Sorry, I didn't mean to disappear. It's been quite a week. I greatly appreciate your time and the discussion!

If you want just 5 unique values, you can simplify the interrupt sampling code to measure pulse width low, rather than extract individual bits

I like this idea, thanks! Parsing is easier. Also 2 of my messages are much more likely than the others, so I can transfer that data more quickly. The latest plan is now to have a start bit high 2.5ms, then a variable width pulse low in multiples of 2.5ms, then hold high until the beam is no longer broken (effectively like a stop bit). Noise < 2.5ms gets ignored.

That is not the way RS485 is supposed to work.

Normally you only need 9 devices. One for each node (that is 8) and the ninth is for the "master", and then you daisy chain all the nodes on a single cable.

I have home runs from each sensor to my ESP32. Many go off in different directions, making a star network. RS-485 needs stubs as short as possible, so I'd need a transceiver for each sensor. TBF a few sensors could be daisy chained, but it would require a redesign and make the sensors larger to accommodate output to the next sensor. Also I'm building a house and it's easier to get my GC to run cables to a central location than to give daisy chain instructions.

Quote
I'm also weary of Maxim chips. They have a reputation of making quite nice specialized chips, and after a bunch of years they get progressively more expensive and get obsoleted. I am more for buying more standard chips that are interchangeable between different manufacturers.

That seems reasonable. I don't yet have enough experience to have enjoyed that.

I looked at a bunch of RS-485 parts before settling on MAX14787E. It's been a while and I don't remember all of my reasoning. Sometimes component review can be very exhausting! I often pass on components with terrible datasheets, leading me to Maxim/TI/etc. I remember needing 3.3V and 5V. This one stands apart from others in that it's fail-safe and slew rate limited, for what that's worth.

Quote
RS485 transceivers have a quite common pinout

I absolutely love that no one agrees what A and B should mean! Mixing up RX/TX wasn't easy enough!

I looked at Modbus and CAN protocols (for my other projects, not these sensors), but felt they added too much complexity for my simple needs. These sensors were intended to be binary, so I skipped using a proper transmission line. That makes the hardware simpler but now it's biting me a little. Worst case if solving it in software is a bust, I'll redesign it in a better way.

Originally they were just a break bream sensor. Now I want to have some "gestures" like breaking the beam near or far, or breaking the beam and moving towards or away.

The sensors are for motorized sliding doors. The laser shoots from the ceiling to the floor, along the edge of the door where it opens. Breaking the beam will open the door, then close it after a delay. Breaking it high or gesturing up/down can do other things, like toggle screen/glass doors or open everything all the way. I discard breaking the beam too low to the ground, so dogs can't open it. It's all completely unnecessary but also super cool! StarTrek doors! 8)

TVS diodes and PPTC resistors are interesting, thanks. I've read about them but have not gotten to play with them firsthand. The sensors aren't handled a lot, once installed I hope to never touch them again. Given that, extra protections for handling or incorrect wiring may not be worth it.

Quote
And I still don't completely understand your use of optocouplers. How do you power your remote nodes? I guess it's from the same long cable.

Yep!

Quote
Do you also use isolated SMPS modules for this, or are the ground pins of your uC's connected to the GND of your wiring?

Power to remote MCUs comes from an isolated supply. My ESP32s use PoE, so I'd rather not have those electrically connected to the remote MCUs, especially where the wires are routed outside.

The differential nature of CAN/RS-485 is really neat! Also thanks for the PDF, it was a good read.
« Last Edit: August 13, 2023, 05:33:57 pm by n4te »
 

Offline n4teTopic starter

  • Regular Contributor
  • *
  • Posts: 56
  • Country: pr
Re: Sensor digital signal with optocoupler
« Reply #16 on: August 23, 2023, 08:14:37 pm »
Quote
I have home runs from each sensor to my ESP32. Many go off in different directions, making a star network. RS-485 needs stubs as short as possible, so I'd need a transceiver for each sensor.

I was thinking of what I said here. I could use "out and back" wiring to make the star network usable for RS-485. The total length would get to around 500-600', but still well within the RS-485 limits.

I came across a "typical application circuit" in the MAX13487E datasheet that is exactly what I'm doing with my optocouplers (except full duplex with MAX14787E):



Sadly I goofed using MAX13487E for a different project -- I forgot the pull up and pull down. I will try to hack those in.
 

Offline n4teTopic starter

  • Regular Contributor
  • *
  • Posts: 56
  • Country: pr
Re: Sensor digital signal with optocoupler
« Reply #17 on: August 23, 2023, 11:52:36 pm »
I'm happy to be lucky enough to find places to add resistors. Salvaged it! Pull down:


Pull up:


The last one shows the MAX13487E and optos.

Everything on the board is now working great!  8) 8) 8)
« Last Edit: August 24, 2023, 01:27:47 am by n4te »
 

Offline larsdenmark

  • Regular Contributor
  • *
  • Posts: 138
  • Country: dk
Re: Sensor digital signal with optocoupler
« Reply #18 on: August 24, 2023, 12:15:12 pm »
Since you just want to transfer 3 bits (i.e. values from 0 to 7) and doesn't seem to require it to be super fast you can simply send pulses. One pulse for 0, two pulses for 1, ... 8 pulses for 7. Then you insert a delay and start transmitting again.

It is a similar idea to the LMT01 temperature sensor:
https://www.ti.com/lit/ds/symlink/lmt01.pdf
except this one send up to 3228 pulses per measurement.


 

Offline n4teTopic starter

  • Regular Contributor
  • *
  • Posts: 56
  • Country: pr
Re: Sensor digital signal with optocoupler
« Reply #19 on: August 24, 2023, 02:55:04 pm »
Thanks! It's interesting the LMT01 uses current pulses, converted to voltage with a resistor. I wonder why it sends a potentially high pulse count (output is (pulseCount / 4096 * 256C) - 50C) rather than just a few bits?

I looked into using a 4-20mA sensor once, but it did not seem easy to make use of the output, so I ended up sticking with what I'm more familiar with. I suppose since 4-20mA is analog it's harder to make use of than digital current pulses.

For my ToF sensors I am now using a single pulse with varying width, plus a start and stop bit, like this:



The counts for holding high or low for the different states are unique, so if my receiver starts reading the middle of a communication or otherwise gets confused, it won't be detected as valid data. I use a 2.5ms bit time and read it using an ISR with +/-0.25ms tolerance. In case it helps someone in the future:

Code: [Select]
#define BIT_MICROS 2500 // 2.5ms = 400 baud
#define TOLERANCE 250 // 0.25ms (150 is typical, 350 is usually erroneous)

#define STATE_IDLE 0
#define STATE_START 1
#define STATE_DATA 2
#define STATE_HOLD 3

typedef struct Sensor {
volatile uint8_t event;
volatile bool longTime;
volatile uint32_t time;
volatile uint8_t state;
uint8_t pin;
Sensor (uint8_t pin) : event(0), longTime(false), time(0), state(STATE_IDLE), pin(pin) {}
} Sensor;

static Sensor *sensors[8];

static void IRAM_ATTR isr (void* context) {
uint32_t now = micros();
Sensor *sensor = (Sensor*)context;
uint8_t level = digitalRead(sensor->pin);
uint32_t elapsed = now - sensor->time;
sensor->time = now;
switch (sensor->state) { // http://n4te.com/x/8012-LTIg.png
case STATE_IDLE: // 5+ bits high
if (!level && (sensor->longTime || elapsed >= BIT_MICROS * 5 - TOLERANCE)) sensor->state = STATE_START;
break;
case STATE_START: // 1 bit low
if (level && elapsed >= BIT_MICROS - TOLERANCE && elapsed <= BIT_MICROS + TOLERANCE && !sensor->longTime)
sensor->state = STATE_DATA;
else
sensor->state = STATE_IDLE;
break;
case STATE_DATA: // 1-4 bits high
if (!level && elapsed >= BIT_MICROS - TOLERANCE && elapsed <= BIT_MICROS * 4 + TOLERANCE && !sensor->longTime) {
sensor->state = STATE_HOLD;
sensor->event = (elapsed + TOLERANCE) / BIT_MICROS;
} else
sensor->state = STATE_IDLE;
break;
case STATE_HOLD: // 2+ bits low
sensor->state = STATE_IDLE;
break;
}
sensor->longTime = false;
}

void setup () {
uint8_t pins[8];
  pins[0] = 2;
pins[1] = 5;
pins[2] = 12;
pins[3] = 14;
pins[4] = 13;
pins[5] = 18;
pins[6] = 23;
pins[7] = 32;

// Don't use attachInterrupt so context can be passed.
gpio_install_isr_service(0);
gpio_config_t gpio;
for(uint8_t i = 0; i < 8; i++) {
Sensor* sensor = new Sensor(pins[i]);
sensors[i] = sensor;

pinMode(sensor->pin, INPUT_PULLUP);

gpio_isr_handler_add((gpio_num_t)sensor->pin, isr, sensor);

gpio.pin_bit_mask |= 1ULL << sensor->pin;
}

gpio.mode = GPIO_MODE_INPUT;
gpio.pull_up_en = GPIO_PULLUP_ENABLE;
gpio.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio.intr_type = GPIO_INTR_ANYEDGE;
gpio_config(&gpio);

INFO("Ready!");
}

void loop () {
uint32_t now = micros();
for(uint8_t i = 0; i < 8; i++) {
Sensor* sensor = sensors[i];
uint8_t event = sensor->event;
if (event) {
sensor->event = 0;
send(MSG_DATA, i | (event << 3));
INFO("Event: ", event);
}
if (!sensor->longTime && now - sensor->time > BIT_MICROS * 5 - TOLERANCE) sensor->longTime = true; // So rollover can't affect elapsed checks.
}
}
« Last Edit: August 24, 2023, 02:58:44 pm by n4te »
 
The following users thanked this post: PCB.Wiz

Offline larsdenmark

  • Regular Contributor
  • *
  • Posts: 138
  • Country: dk
Re: Sensor digital signal with optocoupler
« Reply #20 on: August 24, 2023, 08:28:55 pm »
The LMT01 only has two wires that both handles power and signal. It sends the pulses as current since that allows the leads to the device to get very very long. I don't think you can utilize these two features for your design.

But handling the signals as a set of pulses makes it super easy to handle the signal using an interrupt. The interrupt handler then just has to increase a counter whenever it is called. There is no complicated/magic protocol handling you need to take care of.
 

Offline n4teTopic starter

  • Regular Contributor
  • *
  • Posts: 56
  • Country: pr
Re: Sensor digital signal with optocoupler
« Reply #21 on: August 24, 2023, 09:31:03 pm »
Oh right, I missed the power aspect! It's really neat.

Receiving pulses is indeed pretty simple, though if you tuned in mid-message you'd hear an incorrect pulse count. I like that my scheme can't be misinterpreted. I don't mind a little extra complexity for parsing, that's half the fun!
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf