I am looking for help with my PWM Exhaust valve controller project please

Hi all.

Firstly I would like to share my project with you and then I have a question at the end.

I have started a project which involves making an exhaust valve controller. I have an exhaust valve kit which I got from China. All works as it should and the quality is surprisingly good. The servo motors look identical to the BMW OEM valves.

I could just fit them as they are and be done with it, but where is the fun in that.

I haven't opened the valves as I don't want to compromise the watertight seal. I did, however, find this picture online.


https://drive.google.com/file/d/1BSzoeBEYh86eMxuGCRtSuqhLYpue2kdc/view?usp=sharing

It's not the best picture but some of you pros may be able to work it out. I'm thinking maybe an H bridge?

I had a look in the controller itself and got pictures of the circuit board. It runs on a Nuvoton N76E003AT20 chip and the PWM signal is bumped up to 12V.

IMG_4871.JPG

I have been working on some code with the help of some of the guys on here to control 2 servo motors. I have got the code to do all the things it needs to do to move the valves from 0 to 180 and so on, every time a button is pressed.

const int  buttonPin = 2;    // the pin that the pushbutton is attached to
const int servoPin1 = 9;
const int servoPin2 = 10;


// Variables will change:
int buttonState;         // current state of the button
int lastButtonState;     // previous state of the button
bool servoFacingLeft;




#include <Servo.h>
Servo myservo1;
Servo myservo2;

void setup()
{
  Serial.begin(9600);          //  setup serial
  // initialize the button pin as a input with pullup, active low
  pinMode(buttonPin, INPUT_PULLUP);
  //initialize button states
  buttonState = digitalRead(buttonPin);
  lastButtonState = buttonState;
  //servo
  myservo1.attach(9);
  myservo2.attach(10);
  Serial.println("Exhaust Valves "); 

}

void loop()
{
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) //changed
  {
    if (buttonState == LOW) //new press, so change servo flag
    {
      servoFacingLeft = !servoFacingLeft;
    }
    delay(50);
  }

  lastButtonState = buttonState; // save the current state as the last state, for next time through the loop


  if (servoFacingLeft) //positions the servo
  {
    myservo1.write(-180); // 180 or -180 depending on type of valve
    myservo2.write(-180); // 180 or -180 depending on type of valve
    Serial.print("Valve Status: ");
    Serial.print(" Valve Open");
    Serial.println(" (Loud Mode)");
    
    {


    }
  }    else
  {
    myservo1.write(180); // 180 or -180 depending on type of valve
    myservo2.write(180); // 180 or -180 depending on type of valve
    Serial.print("Valve Status: ");
    Serial.print(" Valve Closed");   
    Serial.println(" (Quiet Mode)");
    
  }
}

I connected the Arduino circuit up to an oscilloscope and you can see the results in the following pictures.

At 180,

IMG_4961.JPG
https://drive.google.com/file/d/1LQfvC1vZmd0faboLnpJmYx0ok5YT6Udz/view?usp=sharing

IMG_4962.JPG
https://drive.google.com/file/d/1hrqO0bovOCBghC8Da-FTtMaBhOaLf-U-/view?usp=sharing

And at -180 or 0

IMG_4963.JPG
https://drive.google.com/file/d/1f1HVEnEfYJmuyypoSCN8RhwcdaXfHgYh/view?usp=sharing

IMG_4964.JPG
https://drive.google.com/file/d/1e1ou9MIAFmtwxXt4q8nuZ7p5E8T78AGl/view?usp=sharing

This is fine for the micro servos on the Arduino but not for the exhaust valves.

I hooked up the oscilloscope to the valve controller and came up with the following results.

There is a constant 11-12v signal being produced and when the button on the remote is pushed it looks like the PWM signal drops to around 0V like a reversed PWM signal if that is the correct term. see the following photos.

when the controller is at idle, constant 11-12V.

IMG_4966.JPG
https://drive.google.com/file/d/16Oi6elP4Dn8oqVMvZdappC09suJVNqC_/view?usp=sharing

When the OFF button is pressed (Valve Closed).

IMG_4976.JPG
https://drive.google.com/file/d/1lq-EAeitjpsRkRLM4j3EwtbiKrSMtWis/view?usp=sharing

IMG_4977.JPG
https://drive.google.com/file/d/1UCPo3eMPeBMM2_4ZrB9OSkiiZOCfFUW-/view?usp=sharing

When the ON button is Pressed (Valve open).

IMG_4978.JPG
https://drive.google.com/file/d/1aZ2VZ-hzyTajETbnBM77nJ-aqyX6u-IL/view?usp=sharing

IMG_4979.JPG
https://drive.google.com/file/d/1OMwDldNCrwTSCN0ak69UY46zLPuZ0o40/view?usp=sharing

Now to me, the signal looks the same when pressing ON or OFF but if you keep pressing the ON button when the controller is ON you can see the signal on the scope but nothing happens until you press the OFF button and the same goes for the OFF button. When each button is pressed it pulses for around a second and then returns to the constant 11-12v signal.

this is the first time using an oscilloscope so I may be doing it all wrong and hopefully, you guys can point me in the right direction if so.

Now the big question is..... Can I replicate the frequency and duty cycle of the valve controller and place it in the correct places in my code?

I basically want to control the valves with a momentary push button and in the future ad geofencing and time disable (Valve Closed) so not to wake the neighbours on early morning starts.

I have found a link to a BMW site with information of their valves which may be similar to my valves.

https://www.newtis.info/tisv2/a/en/f31-340i-tou/wiring-functional-info/power-train/engine-electronics/exhaust-emission-system/Im2GgsKi

Kind Regards,
Mike.

IMG_4871.JPG

IMG_4976.JPG

IMG_4977.JPG

IMG_4978.JPG

IMG_4979.JPG

TL/DR - sorry

Can you just summarise your question in a few lines? Then if I think I can help I might take the time to read the details.

And please make you images visible in your post. See this Simple Image Guide

...R

I thought people might want to see the project so they can see the facts and figures and get an idea of what I am trying to do.

I used the image insert link but it doesn’t seem to work.

I resized all my pictures so I could add them as attachments.

I added some of the pictures as attachments and copied the address but now being told I have run out of attachment space.

I added ;image at the end of the links and still didn’t work.

I give up!

Mike.

IMG_4961.JPG

IMG_4962.JPG

IMG_4963.JPG

IMG_4964.JPG

IMG_4966.JPG

s200bym:
I thought people might want to see the project so they can see the facts and figures and get an idea of what I am trying to do.

If that means that this Thread is intended to be instructional it may be better moved to the Exhibition / Gallery section. If you click Report to Moderator you can ask for it to be moved.

(I had assumed you were looking for assistance with something)

I used the image insert link but it doesn’t seem to work.

Seems to have worked for some of them

...R

Robin2:
Seems to have worked for some of them

...R

edited the last post.

Robin2:
(I had assumed you were looking for assistance with something)

You assumed correctly. There is a question in there asking if I can replicate the frequency and duty cycle from the controller and add it into my code. I wanted to make sure everyone got the information before I asked the question.

Mike.

Robin2:
Seems to have worked for some of them

...R

A bit of a backwards way of doing it, but I have sorted the picture issue.

Mike.

s200bym:
There is a question in there

That was the purpose of Reply #1 :slight_smile:

if I can replicate the frequency and duty cycle from the controller and add it into my code

Do you mean that you want your Arduino to detect the frequency and duty cycle and then repeat it?

OR

Do you just want to write a program that can replace the controller by producing a particular frequency and range of duty cycles that mimics the controller. (What controller?)

...R

Robin2:
Do you just want to write a program that can replace the controller by producing a particular frequency and range of duty cycles that mimics the controller. (What controller?)

...R

Yes, that is correct. The controller is based on a Nuvoton N76E003AT20 chip as shown in my OP with a picture of the PCB. I don't have access to the code for the controller. I have code which I have tested on servos but the PWM frequency on the Arduino is different to the valve controller. I want to mimic the frequency from the valve controller and place/modify it within my code but I don't know how or where to start and seeking guidance. I have shown the valve controller frequencies in my OP.

Mike.

What PWM frequency do you require?

If you study the Atmega 328 datasheet (assuming you are using an Uno or Nano) you will see how to define the frequency. The standard Arduino PWM frequency is about 490 Hz.

...R

Looking at the scope and if I am reading it right, it looks like it is showing an inverted PWM signal with 11v-12v and when a button is pressed the signal drops to 180mv/190mv with a 2.4khz frequency and 50% duty cycle.

I'm using the UNO ATmega328p

I presume you realize that you will need external components if your signal needs to work with voltages other than 0 to 5v.

I have been doing a little research on this for my own needs and I am not sure exactly what frequencies are possible. You will get the widest range with 16 bit Timer1 which works on Pins 9 and 10. IIRC the standard Arduino code divides the 16MHz frequency by 64 in order to get the 490Hz frequency with phase-correct PWM. The same divisor would give about 980 Hz with fast PWM. And you can divide by 8 or by 1 rather than 64 for higher frequencies.

I think you can get intermediate frequencies if you are prepared to sacrifice resolution.

...R

Yes, I have upped the Arduino 5V PWM signal to 12V as you will see in the picture below.

IMG_4962.JPG

I keep reading this and trying to get my head around it, but I'm struggling with the jargon.

I really struggle with understanding code and what makes it worse is, I see people post tutorials of the same thing but do it completely differently. I try to get ideas from other people and get bits of their code and try to write my own code but it never works.

I get to a point to where I think I understand it, but when I go to compile my own sketches I just get errors and haven't a clue where I'm going wrong.

Mike.

s200bym:
I keep reading this and trying to get my head around it, but I'm struggling with the jargon.

I saw that link and I deliberately did not suggest it. :slight_smile:

I agree the jargon is confusing and the Atmel Datasheets seem like they were deliberately designed as substitutes for sleeping pills. But stick at it. I find it begins to make sense after the 14th read. Write a short program so you can experiment and see the effect of the jargon on your 'scope.

...R

Thanks, Robin2.

I have been having a poke around with the scope on the valve controller and the signal gets inverted with a transistor just before it gets bumped up to 12v, which makes things a little easier when it comes to coding (I say a LITTLE easier).

3v PWM Signal coming from the chip

Valve Closed 3v.jpg

Signal boosted to 12v and inverted

Valve Closed 12v.jpg

Mike.

Valve Closed 3v.jpg

Valve Closed 12v.jpg

Did you get along with driving the actuator ?
I am also generating a 5V PWM with the digital output of arduino and with a transistor doing the 12V to pull the one line to GND.
Which frequency did you use ?
I have the same actuator but nothing happens with 100Hz , I think I even tried other frequencies.....

Did you ever get it working....
Could you please share schematics???

I'd appreciate your help.....

THX
Al

1 year later, I now have the Code working and activating the valves correctly.

What I want it to do is, every time the button is pressed it runs the serial hex code then shuts off until the button is pressed again.

As the code is now, it is constantly running a 5V signal. I only want it to run the hex code when the button is pressed then stop until the next press. I have put a while function in to stop it sending a signal but there is still a +5v signal,

how can I incorporate the serial.end() in there or is there another function I could use?

Cheers,
Mike.

int LED1 = 8; // Indicates Valve Closed
int LED2 = 9; // Indicates Valve Open
int LED3 = 10; // Power/Programme Running
 
const int  buttonPin = 3;    // The pin that the pushbutton is attached to
const int valvepin = 1;      // The pin that the valves are attached to

int period = 15000;
unsigned long time_now = 0;

// Variables will change:
int buttonState;         // Current state of the button
int lastButtonState;     // Previous state of the button
bool valveStatus;



void setup()
{
  Serial.begin(9600);          //  Setup serial
  // Initialize the button pin as a input with pullup, active low
  pinMode(buttonPin, INPUT_PULLUP);
  //Initialize button states
  buttonState = digitalRead(buttonPin);
  lastButtonState = buttonState;




  Serial.println("Exhaust Valves ");
  pinMode (LED1, OUTPUT);
  pinMode (LED2, OUTPUT);
  digitalWrite (LED3, HIGH);

}

void loop()
{
  // Read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // Compare the buttonState to its previous state
  if (buttonState != lastButtonState) //Changed
  {
    if (buttonState == LOW) //New press, so change valve flag
    {
      valveStatus = !valveStatus;
    }
    delay(50);
  }

  lastButtonState = buttonState; // Save the current state as the last state, for next time through the loop


  if (valveStatus) //Positions the valve
  {
    Serial.write(0x56);
    Serial.write(0x31);
    Serial.write(0x0A);

    Serial.print("Valve Status: ");
    Serial.print(" Valve Open");
    Serial.println(" (Loud Mode)");
    digitalWrite (LED1, LOW);
    digitalWrite (LED2, HIGH);
     {
while (digitalRead(buttonPin) == HIGH);
  }
    delay (200);

  }
  else
  {
    Serial.write(0x56);
    Serial.write(0x30);
    Serial.write(0x0A);

    Serial.print("Valve Status: ");
    Serial.print(" Valve Closed");
    Serial.println(" (Quiet Mode)");
    digitalWrite (LED2, LOW);
    digitalWrite (LED1, HIGH);
     {
while (digitalRead(buttonPin) == HIGH);
  }
    delay (200);

  }

}

s200bym:
1 year later, I now have the Code working and activating the valves correctly.

What I want it to do is, every time the button is pressed it runs the serial hex code then shuts off until the button is pressed again.

As the code is now, it is constantly running a 5V signal.

Good to hear you are making progress.

However, as you say, it's a year later. You have probably spent a lot of time thinking about it during that time but I'm afraid I have not. So if my name was not alongside some of the earlier Replies I would not even remember that I had helped and I certainly don't recall any of the details.

So, some very basic questions ...

  • What serial hex code?
  • What is the purpose of the hex code?
  • Where does it come from?
  • What does "running a 5v signal mean"?
  • I can't make any connection in my mind between "5v signal" and "serial hex code" - how can they be interchangeable?

...R

Hi Robin2

thanks for your reply.

See the Hex codes below, this is what is sent from the Arduino via serial TX Pin 1 to the exhaust valves to open or close them. It is UART protocol.

Serial Hex Code 1 opens the valves.

    Serial.write(0x56);
    Serial.write(0x31);
    Serial.write(0x0A);

Scope View.

Serial Hex Code 2 closes the valves.

    Serial.write(0x56);
    Serial.write(0x30);
    Serial.write(0x0A);

Scope View

With the +5v signal. TX Pin 1 is constantly outputting +5v regardless. If I Serial.end(); at the end of the Hex code it drops to 0V which is what I want it to do but when I press the button again it won't move/execute the next hex code.

See picture below from the scope where TX Pin 1 is sitting at a constant +5V.

Hope this helps?

Here is a quick Tinkercad mock test
Mike.

Is there a way to put the ATmega328p chip to sleep/standby until the button is pressed again like the sequence below?

Button press -> execute code for valve open -> sleep/standby after 1s -> button press -> execute code for valve closed -> sleep/standby after 1s. and so on.

Mike

s200bym:
With the +5v signal. TX Pin 1 is constantly outputting +5v regardless.

That is the normal behaviour of the serial system - it idles in the HIGH state.

From your comments so far I can't figure why that matters.

If you want to be able to turn that signal off and on you could feed it through an external logic AND gate with the other input to the AND gate coming from another Arduino I/O pin. The output of the AND gate would only be HIGH when both inputs are HIGH.

I believe if is possible to have the Atmega 328 wake from sleep with a button press but I don't know the details. However if the only purpose of the SLEEP is to get the Tx pin to go LOW then I bring you back to my question - why is that necessary.

...R