Working with pwm

Contemplating a project. Wondering if it's possible.
Need to take a pwm output from an agricultural monitor and adjust it by a percentage depending on whether a different pair of outputs has voltage or not.
For example. If both outputs are off, then send the same pwm out. If only output 1 has voltage then the pwm will be lowered by the monitor to 53% of the original pwm. I want to scale the output back to 100%. When only output 2 has voltage, the pwm will be lowered by the monitor to 46% of the original pwm. If both have voltage, then I believe the monitor will turn off the pwm.
The actual pwm sent by the monitor is constantly variable depending on the speed of the tractor. The pwm is adjusting a hydraulic valve that controls the speed of a hydraulic motor.
Along with this, I need to adjust a speed sensor signal to make the monitor think the machinery is actually running at the commanded rate rather than my adjusted rate. I believe the sensor is a proximity sensor running off of the teeth of a sprocket.
Clear as mud?

  • Always show us a good schematic of your proposed circuit.
    Show us good images of your ‘actual’ wiring.
    Give links to components.

  • In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.
    Use the < CODE / > icon from the ‘posting menu’ to attach the copied sketch.

1 Like

What you want to do is called spoofing. The tractor has one output -- the PWM signal to the hydraulic motor -- and one input, the speed sensor on the sprocket.

Your circuit is going to have four inputs -- the PWM from the tractor, the speed sensor, and the two buttons -- and two outputs: your PWM signal to the hydraulics and a spoofed speed signal back to the tractor.

You need to figure out how to do four things:

  1. Read the PWM signal produced by the tractor
  2. Read the speed sensor
  3. Create a PWM signal that the hydraulic motor responds to
  4. Create a spoofed speed signal that the tractor responds to

Each one of those things by itself is something an Arduino is capable of. The first step would be to measure the signal characteristics -- voltage, frequency. Depending on what they are it might be simple and it might be complicated.

Then do some experimentation. I would start by trying to make a proof-of-concept that does the four things listed above, and just acts as a pass-through.

Is there any kind of display where you can see what the tractor is seeing?

2 Likes

There is a display. I'm not sure what it will show. I will have to investigate.
Ideally what would be helpful information?
This project is for a friend that runs the equipment. It's going on a fertilizer machine. We need to shut part of the machine off to avoid overlap. The monitor module we want to use can turn off the sections (that's the 2 voltage outputs), but it wants to adjust the hydraulic motor speed at the same time to apply the correct amount. The machine we have needs the motor o run at full speed regardless of how many sections are on. The speed sensor is on the motor shaft, so it would slow down as well. The sensor is feedback to the monitor to calculate the correct application amount.
How would I go about building a test rig to figure out the requirements of the program?

If the display shows shaft rpm, you would use that to debug three of the four processes:

  • Read the speed sensor: the display would tell you if what you're doing to read the speed sensor is giving the right result.
  • Create a PWM signal that the hydraulic motor responds to: the display would tell you if your signal is giving the desired outcome.
  • Create a spoofed speed signal: the display would tell you if your spoofed signal is tricking the tractor.
1 Like

I'll find out if that information is available.
My Arduino coding is a little limited. Do you have any pointers on coding a project like this?

Break it into as many small pieces as you can, and get each piece working independently before you try to put it all together.
Q: How do you eat an elephant?
A: One bite at a time.

Above I laid out the four capabilities you need in order for this to work. Each of those can be developed independently. If you need help, I would post separate questions -- "how do I read a PWM signal?" or "how do I write a PWM signal?" or "how do I read the on/off status of a switch?" When you break it down like that you also get something that you can Google or search the archives here for because it's a simple question.

Once you have those four capabilities, you need a loop that pulls it all together. I would think it would look something like this:

  1. Read PWM output from tractor.
  2. Read the output from the shaft.
  3. Read the two switches.
  4. Take those three inputs and calculate what PWM you should be transmitting to the hydraulic motor. Adjust, if necessary.
  5. Take those three inputs and calculate what shaft speed you should be transmitting to the tractor. Adjust, if necessary.
  6. Wait a decent interval.
  7. Repeat forever

Steps 4 and 5 are where the tricky stuff is. That may have to be determined using trial and error.

Okay, I just talked to my friend and I think this may have gotten simpler.
He thinks if we read and adjust the sensor (600 pulse encoder) to output the scaled down speed back to the monitor when one of the voltage outputs is on, then the monitor will keep the motor speed constant because it will think the motor is now running the correct speed for the section that is still applying. Shouldn't have to mess with the pwm for the motor.
So now I need to figure out how to read an encoder and then output the adjusted signal. Would this be a pwm signal as well?

There are two ways to find out, one is to see if the manufacturer will tell you, the other is to measure the signal directly.

Most likely, it just sends a pulse on every rotation. The way you would measure the speed from that is to detect each pulse and measure the interval between pulses. Since the time between pulses is small, probably a few milliseconds, you will have to use interrupts to measure the time, which is kind of an advanced topic. Searching for "how do I use interrupts to measure the time between pulses on Arduino" should get you started.

Creating the pulses can be done using the PWM built into the Arduino, but you'll need to change the frequency which is also an advanced topic.

Most Arduinos operate at either five volts or 3.3 volts. Most farm equipment is at 12 volts. You will have to figure out a way to translate between the different voltages, both on the input and the output. Another thing you can Google.

If so, that's not PWM but pulse rate (pulses per second or milliseconds between pulses).

1 Like

So do you need to scale up a 600 pulse per revolution signal into a 600/0.53 = 1132PPR and 600/0.46=1304PPR signals to feed them back into the first motor to slow its RPM? Or to scale them down to 600*0.53 = 318PPR and 600*0.46=276PPR to feed them into the second system?

About how many RPM is the first motor turning the 600PPR sensor encoder?

1 Like

Sorry, I was a little confused on exactly how the system works. The speed sensor is an encoder, I believe it is 600 pulses per rotation. I think it's just using 1 channel, since it doesn't need to know the direction of travel. When the machine is running and one section turns off, I want to scale the encoder pulses returned to the monitor down, so it believes that the machine is running at a slower speed than it actually is. This will keep the motor running at the same speed as before.
The reason for the 2 different scale factors is because the machine isn't split exactly in 1/2. There are a total of 13 rows, so it's split 6&7.
So basically I need to figure out how to read the encoder, scale it if necessary and send it back out. The scale is determined by which section, if any, is turned off. If both sections are on, then the encoder is sent right through.

I've tinkered with Arduinos a while back, but I'm not sure where to start on this. How do I get this to run without delays? How do I handle the 12v power system?

OK, so the pulse-train would be used by the second system would be scaled down and slower than the 600PPM inputs. The nice thing about delivering a slower series is that you could key off of the faster input series, and either pulse the output or not depending on whether it owes a slower pulse or not. There is an excellent algorithm for doing this very fast and accurately: (the Bresenham Algorithm)

You could build without delays off of the StateChangeDetection example:

https://docs.arduino.cc/built-in-examples/digital/StateChangeDetection/

...with some extra logic to use the Bresenham Algorithm to make the different speed pulses. For example:

/*
  State change detection (edge detection)
  2024-05-05: modified to do a Bresenham PLL ratio of pulses between the input and output
  for https://forum.arduino.cc/t/working-with-pwm/1256186/13
  https://wokwi.com/projects/397099785583173633

  Often, you don't need to know the state of a digital input all the time, but
  you just need to know when the input changes from one state to another.
  For example, you want to know when a button goes from OFF to ON. This is called
  state change detection, or edge detection.

  This example shows how to detect when a button or button changes from off to on
  and on to off.

  The circuit:
  - pushbutton attached to pin 2 from +5V
  - 10 kilohm resistor attached to pin 2 from ground
  - LED attached from pin 13 to ground through 220 ohm resistor (or use the
    built-in LED on most Arduino boards)

  created  27 Sep 2005
  modified 30 Aug 2011
  by Tom Igoe

  This example code is in the public domain.

  https://docs.arduino.cc/built-in-examples/digital/StateChangeDetection/
*/

// this constant won't change:
const int buttonPin = 2;  // the pin that the pushbutton is attached to
const int ledPin = 13;    // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;  // counter for the number of button presses
int buttonState = 0;        // current state of the button
int lastButtonState = 0;    // previous state of the button
int outState = LOW; //  current state of the output pulser
int lastOutState = LOW;
int outPulseCounter = 0;

// pulse ratio constants 

const unsigned int inputPPR = 600;
unsigned int outputPPR = inputPPR * 53UL /100;

int bresenhamSum = inputPPR/2;

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(115200);
  Serial.print("");
}

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

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == LOW) {
      // if the current state is HIGH then the button went from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes: ");
      Serial.println(buttonPushCounter);
      bresenhamSum += outputPPR;
      if(bresenhamSum >=inputPPR)
      {
        bresenhamSum -= inputPPR;
        outState = HIGH;
        ++outPulseCounter;
      }
      Serial.print("number of outputPulses:");
      Serial.println(outPulseCounter);
      Serial.print("Bresenham Decision Sum:");
      Serial.println(bresenhamSum);
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
      outState = LOW;
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;


  // toggles the output to match the outState when it changes:
  if (outState != lastOutState) {
    digitalWrite(ledPin, outState);
    lastOutState = outState;
  }
}

Note that this code is slow with all the debouncing, printing, and diagnostics from the example, and might not be able to keep up with the (unknown/fast?) RPMs of your system, but it also demonstrates a very fast way of doing precise output:input ratio calculations with only additions and conditional subtractions.

(Edit: code updated to start 1/2 way between output pulses & reorganize the variables.)

1 Like

I'll have to experiment with the code you posted, but it kind of makes sense. You say it will have delays? How do I overcome this?
I did some research on interfacing with the higher voltage on the tractor. I believe I need to use optocouplers to isolate the higher voltage from the 5v Arduino. This should work for the 2 inputs from the section clutches.
Can I also use the optocouplers for the encoder signals? Will this work for the input and the output?
Then I would use a buck converter to power the board itself.
Does this sound correct?

Guess you've all moved on. Thanks for the tips.

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