Measure PWM signals Ton and Toff with no ICR

Hi everyone !

I've already posted a thread about an issue with a LED on car issue.

Thanks to the comunity, espacially a member with who I discuss a lot by PM. He really helped me a lot as I'm a real newbie...

I'd like to get some ideas so I can find a solution to ly problem...

The issue is simple, I want to read PWM signal without using interruptions (because my program needs to check all the inputs in realtime and continue outputting what's right.

To be short, there is a pulse signal on the car which is at 0.33Hz, and peaking for 100mS at 12V so it checks if hallogen bulbs are okay. But with LED, this signal is enought to light the LED bulb...

So far, we managed to get rid of this signal by using the logic of : do not take into account any signal that's 300mS long (roughly speaking).

The actual code is working fine, stopping LEDs from flickering and when a 1 logical is detected, lasting more than 300 mS (user decides to switch the lights on) it outputs a low signal (inverted logoc) so the desired bulb is lit.

Now, I am facing an issue. Some bulbs on the car are PWM controlled. (Rear tail light, break ligts and rear fog lights). I assume the manufacturer wants to control the brightness so break and fog lights are brighter than tail lights.

What I would desire is that the existing program (mainly created by the member that helps me a lot) measures the duration of ON and OFF (if off is relevent) when dealing with PWM input so I can decide wether to use a 490Hz PWM signal from the arduino proportionally to what's inputting.

Or maybe, because LED and hallogen do not react the same way (meaning the brightness in function of duty cycle), choose the duty cycle that's going to be outputting.

Here is the code made so far, in advance sorry about the amount of comments, even more if they are wrong, I use them so I am sure I understand the program.

/* Author : Deva_Rishi from Arduino's community forum & Bastien DE CUYPER
    Version V1.2
    Created on the :
    Modified on the : 12/03/2022
    Aim of this code : Prevent from the flickering problem on some cars when using LED bulbs, keeping the check bulb function, the brightness ajust with PWM, some with 0/5V DC. (Only Opel Vectra C)
    Versions :
    V1.1 Read signals on inputs, filters if the signal is a PWM pulse of 0.33 Hz (Ton : 10mS - Toff 290ms). When input is +5V DC, gives LOW as output (reverted logic)
    V1.2 Add the feature : PWM input reading capable. The output is a choosen PWM signal (Ton & Toff are inverted because of wiring, meaning inverted logic)
*/

#define NR_INPUT 1 // Size of arrayused in the code
#define TEST_SIGNAL 300 // Set the filter time, if a 1 logical if detected within this time (mS), the code will not output it.
#define PWM_MIN_MAX 18 // Set the max period of a incoming signal (mS)
#define PWM_ON_TIME 3 // sets the Ton max from an incoming PWM signal (mS)

const int signalPins[NR_INPUT] = {5}; // Set inputs pins into array
const int outputPins[NR_INPUT] = {13}; // Set outputs into array

void setup() {
  for (uint8_t i = 0; i < NR_INPUT; i++) {
    pinMode(signalPins[i], INPUT_PULLUP);  // Set type of input of the pins choosen above
    pinMode(outputPins[i], OUTPUT);  // Set the Output pins set above as outputs
  }
}

void loop() {
  static int oldPinState[NR_INPUT]; // Creates a var OldPinState with inputs (static & allow negative values)
  static uint32_t pinChangeMoment[NR_INPUT];  // Create a var PinChangeMoment (static, great size + only positive values)

  uint32_t moment = millis(); // Begining to count the time elapsed since the begining of the program

  for (uint8_t i = 0; i < NR_INPUT; i++) { // Browsing into pins array one by one

    int pinState = digitalRead(signalPins[i]); // Reads the inputs in realtime and store the value in pinState var

    if (oldPinState[i] != pinState) { // If the realtime pin status is different from the status that's been stored in var oldPinState
      pinChangeMoment[i] = moment;  // If the condition is validated, store the time elapsed since the begining of the program in PinChangeMoment var
    }
    if (moment - pinChangeMoment[i] > TEST_SIGNAL) {  // If the time elapsed since the start of the program is grater than the set time we want to filter
      if (pinState == LOW) {  // At this precise moment, if the input reading is LOW, output HIGH (switches off the light cause of revert logic)
        digitalWrite(outputPins[i], HIGH); // Outputs a HIGH state that turns the LED off due to wiring
      }
    }
    else {
      digitalWrite(outputPins[i], LOW); // If the time elapsed is smaller than the time set (filter or pulse test signal), lights the LED
    }
    oldPinState[i] = pinState; // The old pin state stored and used to be compared to the TEST SIGNAL time is now back to realtime value
  }
}

I know it may be obvious to you guys, but not for me :sleepy:.

Hope the comments I made are ok with what lines / blocks are meaning...

To sum up :

  • I have 4 differents signals as input :

1- The pulse test signal (which is dealt with condition of ignoring any signal lasting shorter than 300 mS. (Signal freq. : 0.33 Hz, peak at 12v for 100mS every 3 sec)

2- The PWM signal for the rear tail ligt, break and rear fog light (which I want to detect, measure and deal with it, meaning I can choose what outcomes). Forgot to mention the turning signal lights which are 50% Duty Cycle, in France, where I live, they have to flash between 60 and 120 times per minute.

3- A 12V DC signal which is handled with this code

4 - A 0V DC signal, also dealt with this program, it's in reality the pulse signal...

Some notes : I talking about 12v but the circuit which has been designed had a 7805 to make it 5V, octocoupleur to protect inputs and outputs (used with capacitors to create inrrtia and flyback diodes to prevent from neg. Voltages. As input, the octocoupler output pins are going on one hand to the input, on the other to the GND, reason why I use pull-up inputs.

As interface betzeen 12/5 V on output, TIP120 are used. Also wired so it works when grounded.

The PWM signal on the car is a 68Hz signal with a duty cycle of 20 % for tail ligts. Haven't tested yet for breaks and fog.

I would really appreciate your help to measure the PWM time on that's going to be used to create a fresh new PWM signal or the same. All of them inverted ofc.

Thanks a lot ! :pray:

PS : if it can help, here's the wiring diagram used for one I/O (Same for the code, for the moment).

I'd use Pin Change Interrupts. You record the time of the rising edge. When the falling edge occurs you can calculate the high time. When the next rising edge occurs you an calculate the cycle time.

The PinChangeInterrupt library makes it as easy as External Interrupts (Pin 2 and Pin 3 on the UNO).

  • Little wiring diagram mistake, it's a nano, does not really matter I guess ?
  • This was a solution a was thinking about, but as multiple inputs are to be watched in realtime, using this lib will use interruption and somehow stop the program, doesn't it ?

is it not simpler to rework that strange pulse generator?
in case if it sealed i would make separated schema that analyze signal and say HIGH/LOW or answer via UART/I2C/CAN on request or say when signal changes.

I'm not sure what you mean by "stop the program". An interrupt will use the processor for a few microseconds but then whatever was running will continue. That's how the mllis() timer interrupt happens every 1.024 milliseconds without problem on 99.9% of sketches.

Okay, I was thinking, for instance that assuming tail light are lit.

If the program goes onto an interruption, it won't switch them off, at least what a human can see ?

If so, would you have an exemple of code to show me ?

Thank you :slight_smile:

Edit : Can't I use the existing program and use oldpinstate & pinstate with if conditions ?

For the moment, the code shown above works fine for all bulbs that are not PWM supplied.

I just need to add a feature to this code, capable of detecting a PWM signal then measure it's TIME ON. BTW it's going to be PWM signals that are less than 300mS (period defined at the begining of the program)

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