## Measure square wave signal as high/low

28 posts / 0 new
Author
Message

Dear all,

I am using a Tiny85 to measure a "simple" high/low Situation on one of ist Input (see attached handwritten schematic).

After failing to do so with using Interrupts on rising/falling edges I realized that the Input Signal is a square wave with 200Hz frequency and 50% Duty cycle.

The Signal shall be measured as high when the Amplitude is 9.4V and low when the Amplitude is close to 0V.

Due to the square wave the Interrupt was triggered 200 times per second ,-)

Then I used a low pass filter which worked fine in Terms of clear enough high/low-input for the Interrupt. But the Feedback from the capacitor induced unwanted effects into the inputting signal-circuit.

So I used a Diode to not Feedback into the sourcing circuit but with the effect that the capacitor needed to unload via the Tiny85 which takes too Long.

Finally I ended up with using the ADC. The ADC is measuring 10 times (roughly two square wave periods) and then Building a mean value of that. The mean values are compared and I have my high/low-categorization.

It works and it could be fine. But Maybe there are better Solutions...

The Question is: are there smarter ways? Anything where the ADC does not Need to work all the time? The low-situation will appear only quite seldomly every few Hours but Needs to be detected within maximum 500ms.

This topic has a solution.
Last Edited: Mon. Dec 16, 2019 - 08:40 AM

I don't know exactly what's the problem you want to solve, but one thing I know. The datasheet says:

The ADC is optimized for analog signals with an output impedance of approximately 10 kΩ or less. If such a source is used, the sampling time will be negligible. If a source with higher impedance is used, the sampling time will depend on how long time the source needs to charge the S/H capacitor, with can vary widely. The user is recommended to only use low impedant sources with slowly varying signals, since this minimizes the required charge transfer to the S/H capacitor.

Your voltage divider has large resistors, so the impedance will be way over the recommended 10kΩ you should feed the ADC.

Edit: BTW, you could use the analog comparator instead of the ADC, no?

Last Edited: Mon. Dec 9, 2019 - 12:53 PM

Hi,

After having my PCB in place I've seen the datasheet hint with 10KOhm. But it works well with the 1M/300K-solution. Anyhow I will try to adapt as I only Need to Exchange the resistors.

Even more interesting is your comment About the analog comparator. This was one of the Things I had in mind. What would be the Advantage? I have to measure as well a number of samples to understand whether the square wave Signal is high or low.

At the end I am Looking for a solution where the Tiny85 can Sleep most of the time or at least does not Need to measure all the time although for Hours Nothing is Happening.

Maybe I am wrong and this is exactly what you can expect from a uController. But wouldn't the Lifetime of a Tiny85 much longer if not measuring ADC all the time? The Energy-consumption is not the driving factor.

Ole

PS: does anybody know how to disable this automatic Spellchecker which is writing every second word with capital letter??

With this kind of thing folks usually make the micro sleep for the longest time possible (this may be the longest watchdog period in fact, wake up via a watchdog interrupt) then either do an ADC reading each time it wakes up or alternatively just wake up and increment a counter. When that counter has reached a suitably high number then you do an ADC reading then reset the counter and start the whole cycle again.

(many of the AVRs have a 8 second option for watchdog).

If you add a cap from the ADC pin to gnd, it will do the integration for you and all you have to do is one ADC and compare to your threshold.

It will also solve your input impedance issue too!

Jim

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

Laubfrosch wrote:

After failing to do so with using Interrupts on rising/falling edges I realized that the Input Signal is a square wave with 200Hz frequency and 50% Duty cycle.

...

Due to the square wave the Interrupt was triggered 200 times per second ,-)

...

I fail to see what the problem is. 200 times a second is once every 5ms or and edge every 2.5ms. That's plenty of time to service an interrupt.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Another approach (untested)...

feed your signal into a counter as an external clock. Set an overflow interrupt on that counter so that your 200Hz will cause an overflow after 500ms. Run a timer to routinely clear that counter every 550ms. If the overflow never occurs then your signal has never been present for 500ms or more. If an interrupt does occur then it has. You can play with the two times to adjust the accept/reject window.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Laubfrosch wrote:
Input Signal is a square wave with 200Hz frequency and 50% Duty cycle.

The low-situation will appear only quite seldomly every few Hours but Needs to be detected within maximum 500ms.

You likely already have a timer interrupt running. What rate is that at now ?

You can work backwards, and instead of looking for 200Hz, look for the gaps.

If you have (eg) a 100ms timer, and connect an edge-interrupt-flag to the 200Hz (but do not enable the INT) you now only need to poll/clear that flag every 100ms

If 200Hz is present it certainly will be set in 100ms, if 200Hz is paused, flag is still clear, so you increment a pause CTR, and when that is 5, you have a 500ms pause.

Laubfrosch wrote:

At the end I am Looking for a solution where the Tiny85 can Sleep most of the time or at least does not Need to measure all the time although for Hours Nothing is Happening.

Maybe I am wrong and this is exactly what you can expect from a uController. But wouldn't the Lifetime of a Tiny85 much longer if not measuring ADC all the time? The Energy-consumption is not the driving factor.

Umm, that doesn't make any sense to me. What do you mean by "lifetime of a Tiny85"?

To me this sounds like the perfect job for an input change interrupt. Use resistor network as voltage divider so that 9.4V becomes 3.3V (or whatever your Vcc is). Just let MCU sleep and have it wake up from pin change interrupt. Use a timer to measure number of edges during 500 ms or so. If number of edges is greater than some threshold value (slightly below 100) then you have detected the square wave.

Using ADC seems quite impractical. It would make more sense to just sample and average the digital signal...

/Jakob Selbing

Who-me wrote:
You can work backwards, and instead of looking for 200Hz, look for the gaps.

+1

Sounds like the old "Missing Pulse Detector" with a 555 timer ...

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
This reply has been marked as the solution.

But wouldn't the Lifetime of a Tiny85 much longer if not measuring ADC all the time? The Energy-consumption is not the driving factor.

The Tiny will run for years and years, continuously, if you give it a clean power supply without high voltage spikes and run it within its spec'd temperature range, (i.e. not in an oven!).

(High vibration and thermal cycles and radiation can also shorten its life...)

Some memory, such as the EEPROM, have a limited number of write cycles.

The digital hardware will run "forever".

With power consumption not being an issue, you don't even have to worry about putting the micro to sleep.

As Awneil mentioned, what you are describing is a missing pulse detector.

It can be easily done in hardware or in software.

There are many approaches, but perhaps the one I would use is:

Program a Timer/Counter in CTC  mode to fire an interrupt at 1 kHz.

On each ISR read the input signal, High or Low.

With the 200 Hz signal present, (2.5 mSec per each 1/2 period), the most Low's in a row you can have is 3.

Every time you see a High reset a counter to 0.

Every time you see a Low increment the counter.

If the counter is >= 4 you have a "missing" pulse, i.e. the 200 Hz signal isn't there.

Done.

If you want to add some robustness to the program you can set your missing pulse detector counter higher than 4.

To detect within 500 mSec of the loss of the signal means your counter could count up to 500 before saying that the pulse was absent.

As mentioned above, the pulse detector could use the ADC or the Analog Comparator, (threshold detector).

If you use the ADC, then typically one would set it for one shot mode.

When the ISR fires again you read the (last) ADC reading, trigger the next, exit; repeat forever.

With a simple program the ISR can set a flag with the input signal value, to be processed within the Main Loop, or you just do the signal processing within the ISR as there is so little to actually do, and you have lots of time.  In that case essentially the entire program is ISR driven.

What is the source of the 200 Hz signal?

I agree with the above comments that the impedance of the source driving the ADC input should be <= 10 K ohms.

If that "loads down" the signal source, then you might consider adding an op-amp as a signal buffer (driver).

Of course if you add an op-amp, then you might as well configure the op-amp as the signal comparator, and just feed a digital high or low into a generic I/O pin.

That, of course, is essentially what the Analog Comparator input is for, so you don't need the op-amp.

Report back on how it is progressing.

JC

Do you require 3 high pulses in a row first to "declare" a high, or is it declared after the high first pulse & maintained through the third?  (look like you are attempting groups of 3, but that may simply happen to be the example you drew).

Likewise, does a low require just one low pulse or 3 in a row to make the declaration?

If you say these both require 3 pulses in a row for a declaration, what happen if you get a stream of 2 highs followed by 2 lows, followed by 2 highs, etc... then it is neither case.

Do you just keep the last state & make no change in declaration

Do you declare this other state as "neither", "error", "unknown", "state 2",  etc?

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Tue. Dec 10, 2019 - 02:04 AM

WOW!! I really like this forum. I learned already a lot by reading here and there.

But getting such detailed answers from all over the world which are not written in 10sec is still kind of overwhelming. A gift I really appreciate.

Thanks a lot!! Especially to Cleveland, Ohio.

I learned from all the answers:

• the voltage divider needs to be adjusted
• ADC is maybe not the most appropriate way
• analyzing the high/low at PBx in conjunction with a timer and ISR might be the smarter solution
• keeping a micro running all day long does not influence its lifetime (beside EEPROM writing)

I will rework my setup in the next days.

For the ones interested, here are more details for my project.

• Do you have a Start-Stop-Automatic (SSA) in your car?
• Do you have an automatic gearshift?
• Are you annoyed that the engine goes off in inappropriate situations (e.g. at a T-crossing just before jumping into a free slot)?

I believe the SSA is a good tool in a manual shifted car. There the driver has the control. The system is activated only if you go into neutral and take your feet from the pedals.

But not for automatic gearshift. Then system is active already if pressing the brake pedal and the car is stopped.

With my little project I wanted to build a little helper giving me the same control as for a manual gearshift.

Here is the idea:

• After starting the car the helper presses electronically the SSA-deactivation button (using a transistor-combination).
• The system stays deactivated until I move the gearshift into neutral (here comes the square wave signal from a complex LED-circuit). Once in neutral position the SSA is reactivated by electronically pressing the button again.
• When the gearshift is moved out of neutral position the system becomes deactivated again by electronically pressing the button.
• The whole microcontroller-logic can be deactivated/activated (e.g. if you go into a garage for repair) by pressing the physical SSA-button during startup of micro (status stored in EEPROM).

And this works really cool. For me this is a much better version of the SSA. I use the SSA much more than in the past where I always deactivated it right after start manually. Now it is just a tip on the gearshift. Really easy and with full control.

The issue I had was to get the information if the gearshift is in neutral. I am using the LED displaying the selected gear to get this info. The LED is always on but with different brightnesses. If neutral is selected the LED shines brighter. I tried to do reverse engineering and disassembled the gearshift to get to the circuit. The LED shines brighter if a specific signal is grounded. On top the signal is a square wave as described in first post.

Next step now is to update the logic based on your comments.

If there is interest I can post schematic and coding as well for the ones who want to upgrade their cars. Only issue is about finding the good cable connections ;-))

Thanks again for the exhaustive answers! It keeps me running ;-))

Ole

So you drew 3 pulses, then "no pulses', then 3 pulses...so in reality was this just an aribtrary number you happened to draw?

So in reality maybe you just want to detect whether you are getting pulses or not getting pulses (over some time interval)--that can change the whole requirement.

So I used a Diode to not Feedback into the sourcing circuit but with the effect that the capacitor needed to unload via the Tiny85 which takes too Long.

Add a resistor across the cap...then it will charge up fast via the diode (measure an ADC "high"), and down at some RC rate you can determine (to give an adc"low") during the gap.  Of course such ADC measurement should use  two numerical levels to prevent "result chatter".

For a generic example, consider it "high" whenever the averaged adc reading* crosses >700  and flip the state "low" when the averaged reading falls  <300.... then flip "high" again when the reading >700.etc...etc...etc. So you can travel up & down the RC charge/discharge curve & get only a single  steady 1 per block of high pulses  & a single steady 0 for a block of low pulses.  The difference (hysteresis) between 700 & 300 produces your noise margin.  Of course, maybe your numbers will differ. Maybe that is all you need?

*you can simply continuously average the adc result using something like  Ynew= (7*Yold + Yadc_sample)/8  ...will really smooth it out.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Laubfrosch wrote:
The issue I had was to get the information if the gearshift is in neutral.

Can't you get that from the OBD port ... ?

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

@ avrcandies: I have no clue of how to get data with a microcontroller from that OBD-interface. I guess there is no clear high/low on one of the pins. I would expect that there is a certain protocol to be examined?

@awneil: I will further try this way as well (next to the maybe more simpler one described by DocJC). I will test the various solutions now. For pure understanding of the methods it makes sense for me to test all of them ;-))

Ole

Laubfrosch wrote:
I have no clue of how to get data with a microcontroller from that OBD-interface.

Must be a hundred or more Arduino projects doing just that, so take a look at how they do it.

No my mistake, 3.9 million hits

Jim

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

ki0bk wrote:
Must be a hundred or more Arduino projects doing just that

And plenty of non-Arduino!

Generally, an ELM chip does all the protocol work:

https://www.elmelectronics.com/products/ics/obd/

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

Just use a 6k8Ω~10kΩ resistor from your external voltage to an AVR regular input pin, another 6k8Ω~10kΩ from that pin to ground, or just a 1N4148 diode from that pin to the VCC pin of the AVR (catode to VCC).

The above setup will leave a square wave at such pin, amplitude between zero and ~5V, perfect for the AVR to read it.

You don't need to use the ADC to read the voltage, the logic I/O of the AVR will tell you if the pin is HIGH or LOW.

Now, you need to think how to implement the rest of the software in order to do whatever you want in your car.

Inspiration is 99% of the work, transpiration just 1%.

Plan, design, think, repeat.

Think as if you are the microchip, what would you do to help you?

When you are absolutely sure about what to do visually and manually, then translate that for the microchip to do it for you.

Wagner Lipnharski
Orlando Florida USA

Ole,

So, an automotive project!

Vehicles are tough environments for electronics.

The have very noisy electrical power supply buses.

Google Load Dump in case you are not (yet) familiar with it.

The voltage spikes on a 12 V car bus routinely hit 40 V, and can be 150 V, and the bus can also have large negative voltage spikes!

This means that the power supply design needs to handle a bit more than the normal "wall wart" will send its way.

It also means that any "sensor" inputs from the vehicle to the micro should also be voltage clamped.

They have very wide temperature and humidity ranges.

This makes enclosures challenging if mounted under the hood, instead of inside the passenger compartment.

They experience a lot of vibration.

Hence connectors and wring harnesses have to be handled with care, also.

Sounds like a cool project.

Do spend some time thinking about possible failure modes, and how to mitigate them.

You don't want to be cruising down the Autobahn at Mach 2 and suddenly have your engine stop!

JC

Hi to all,

sorry for being a bit offline. Xmas is calling...

I think I will go the way described by JC. But before doing that I need to adjust my schematic.

Here is what I have so far and where I intend to go. But I am not super sure and your comments are very welcome.

The highlighted double-transistor solution works well but I don't know really why. A pure NPN wasn't doing the button-job. In the shown combination (taken somewhere from the internet) it works.

Now I guess I can exchange the whole highlighted area with just a 'logic-level MOSFET'. Correct?

And for the non-ADC measurement of the square-wave signal with timer and pure digital high/low measurement it might be more clear if I use a pull-up and a NPN-transistor to ground the PIN. Correct?

The good thing is that I do not really get deep into the electronics. I just bypass the physical button. Not much more. So the risk is not too high although in automotive environment.

Thanks a lot for some further comments.

Ole

I think your mosfet is working by pure luck. It is likely to be temperature sensitive.
Your circuit has no protection. What will happen if it fails?

Your mosfet setup is completely WRONG.

First off, the mosfet will always be on, since the AVR gate drive is 0-3.3V & the source is wired to 12V  (so you have a Vgs of 12 to 8.7V under all conditions: ON)

Even if the mosfet were off, the parasitic diode shown would pull SSA up to approx 12V.

Have you considered riding a nice bus or boat, instead?

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Mon. Dec 16, 2019 - 04:59 AM

As well, the Vds of the specified mosfet is 12V maximum.

Okay, okay ;-) I see my knowledge about MOSFETs is still too basic (if not below). I thought with a p-enhancement-MOSFET I could save some parts.
It was a first idea and draft-schematic. I see I need to take more time to understand some backgrounds. Anyhow thanks for the very clear feedback!

The N-channel MOSFET in your schematic is upside down, but a single transistor isn't going to work. Q4 is acting as the switch, while Q2 is needed to translate from 3.3V to 12V. Q2+R4 could be replaced with an N-channel MOSFET and Q4+R5 could be replaced with a P-channel MOSFET.

I thought with a p-enhancement-MOSFET I could save some part

Slightly true, but why did you use an N-channel type?  look at your symbols carefully.

You still need to pull the gate down from 12V, so an npn or other part is needed, since the AVR pin can't provide 12V to swing the gate around.

N @ gnd:  swing gate from gnd (off) to 5V (full on, assuming logic compatible fet)

P @ 12V: swing gate from 12V (off) to 7V (full on, assuming logic compatible fet)

I think taking the ferry to Konstanz is a better option

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Mon. Dec 16, 2019 - 10:04 AM