puseIn / digitalWrite() question

I am controlling a Sabertooth controller using a RC receiver and it works fine. Now I want to intercept the signal from the Rx and make some decisions with a Arduino Pro Mini so I am using the puseIn to get the value from the RC rx, and then based on some rules, either send the pulse to the Sabertooth or not. (haven't got to the rule code yet.

In testing to see if I could pass through the data from the Rx to the sabertooth via the arduino using the puseIn and digitalWrite out, it does not seem to work.

Am I oversimplifying this? Does this even sound possible using some variation of the method below? Any suggestions would be very welcome.

int p2;

void setup() 
{
  Serial.begin(9600);
  pinMode(2,INPUT); 
  pinMode(9,OUTPUT);
  
}
 
void loop()
{
 
   p2=pulseIn(2,HIGH,25000);  // GET THE PULSE FROM THE RECEIVER 
   Serial.println(p2);        // JUST TO SEE WHAT IS BEING RETURNED

  // here is where my future code will go to determine if the pulse should be sent out or not.

   // if the pulse should be passed through.....

   digitalWrite(9,HIGH);      // START THE PUSLE
   delayMicroseconds(p2);     // USE THE INCOMING PULSE WIDTH TO DETERMINE THAT OUTGOING PULSE WIDTH
   digitalWrite(9,LOW);       // END THE PULSE
}

Thank you
Charlie

PWM typically will require a delay in-between pulses as well - so you'll need to do:

timeB = millis();
if ((timeB - timeA) > 20)  // typical delay between pulses
{
   timeA = millis();
   digitalWrite(9,HIGH);
   delayMicroseconds(p2);
   digitalWrite(9,LOW); 
}

in theory it should work if pulseIn() gives you the duration of the pulse.

http://www.ardiri.com/blog/evothings_hacknight_arduino_based_rc_buggy_part_1
http://www.ardiri.com/blog/evothings_hacknight_arduino_based_rc_buggy_part_2

i've done some remote control - it seems thats the only part you are missing :slight_smile: - of course, you'll need to process the data.. but the above should work as a pass-through.

Please forgive me but below when I talk about pin 2,3 5 and 6 on the Arduino, I am actually talking about digital IO 2,3,5 and 6, not the board pin number. :grin:

Still no go. Seems that no signal is making it too the Sabertooth.

The Sabertooth has a BEC +5 so, wiring is....

Sabertooth (ST). +5 to Arduino Vcc and to Vcc on the receiver
(ST) Gnd to Arduino Gnd and Gnd on receiver
Signal 1 on ST to Pin 5 on Arduino (found out pin 9 was not PWM).
Signal 2 on ST to pin 6 on Arduino

Ch1 on receiver to Pin 2 on Arduino
Ch2 on receiver to pin 3 on Arduino.

The serial prints are showing that I am getting what I would expect to get from Ch1 via Pin 2 and Ch2 via pin 3, but no activity from the motors.

If I connect ST signal 1 to cha1 on receiver and ST signal 2 to Cha2 on receiver all works fine, so it seems that the problem lies in the Arduino code somehow.

If the wiring above is not clear, I could do a quick eagle schematic.

int p2, p3
int timeB, timeA;

void setup() 
{
  Serial.begin(9600);

  pinMode(2,INPUT); 
  pinMode(3,INPUT); 
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);

  timeA=millis();
  delay(10);
}
 
void loop()
{

   timeB=millis();
   
   p2=pulseIn(2,HIGH,25000);  // GET THE PULSE FROM THE RECEIVER
   p3=pulseIn(3,HIGH,25000);  // GET THE PULSE FROM THE RECEIVER

  // here is where my code will go to determin if the puse should be sent out or not.

    if ((timeB - timeA) > 20)  // typical delay between pulses
    {
       Serial.print(p2);
       Serial.print(" - ");       // JUST TO SEE WHAT IS BEING RETURNED
       Serial.println(p3);        

       timeA = millis();

       digitalWrite(5,HIGH);      // START THE PULSE
       delayMicroseconds(p2);     // USE THE INCOMING PULSE WIDTH TO DETERMINE THAT OUTGOING PULSE WIDTH
       digitalWrite(5,LOW);       // END THE PULSE

       digitalWrite(6,HIGH);      // START THE PULSE
       delayMicroseconds(p3);     // USE THE INCOMING PULSE WIDTH TO DETERMINE THAT OUTGOING PULSE WIDTH
       digitalWrite(6,LOW);       // END THE PULSE

    }

Signal 1 on ST to Pin 5 on Arduino (found out pin 9 was not PWM).

Pin 9 IS a PWM pin. Why do you think it isn't?

Why are all the other PWM pins being used for non-PWM purposes?

How were you driving the Sabertooth device before you tried bit-banging it?

int timeB, timeA;

Wrong. Time variables are unsigned long.

you do not have to use a PWM pin if you are manually generating the PWM signal - typically, it looks like this:

if you want to use the built in functionality of PWM that is provided by arduino, you use the analogWrite() function on a digital pin, however you may need to tweek the period between and thats why you would do it manually and use digitalWrite()

what you should do is avoid the pulseIn and see if you can drive the servo's directly - try setting values of p2 = 1000 and 2000 which should be the extremes of the servo.. a value of 1500 will mean centre and you wont see much. something like this:

void loop()
{
       digitalWrite(5,HIGH);
       delayMicroseconds(1000);
       digitalWrite(5, LOW);
       delay(20);
    
       digitalWrite(5,HIGH); 
       delayMicroseconds(2000);
       digitalWrite(5,LOW);
       delay(20);
}

if connected to the steering servo should go full left/right repeatedly if you have all the connections correct.

PaulS:

Signal 1 on ST to Pin 5 on Arduino (found out pin 9 was not PWM).

Pin 9 IS a PWM pin. Why do you think it isn't?

Why are all the other PWM pins being used for non-PWM purposes?

How were you driving the Sabertooth device before you tried bit-banging it?

int timeB, timeA;

Wrong. Time variables are unsigned long.

The diagram I was looking at wrongly indicated that pin 9 was not PWM. You are right and I found a fifferent diagram.

I am not sure what you mean about using "all the PWM pins" for non-PWM purposes. I thought I needed the PWM pins for DIO 5 and 6, and the only other PWM pin I am using is DIO 3, which I could easily switch to another digital pin but since I didn't need any other PWM pins, I didn't think it mattered.

Before, I was driving the sabertooth by hooking ch1 to S1 and ch2 to S2. That worked but did not allow me to run any logic against the output of the receiver. The whole point of this is to see if I can intercept the data from the receiver and make some decisions and tests against that data before passing it though to the sabertooth (or preventing it from passing through).

I will change the type for timeA and timeB. Thank you.

Does that answer your questions are am I missing your point.

ardiri:
you do not have to use a PWM pin if you are manually generating the PWM signal - typically, it looks like this:

if you want to use the built in functionality of PWM that is provided by arduino, you use the analogWrite() function on a digital pin, however you may need to tweek the period between and thats why you would do it manually and use digitalWrite()

what you should do is avoid the pulseIn and see if you can drive the servo's directly - try setting values of p2 = 1000 and 2000 which should be the extremes of the servo.. a value of 1500 will mean centre and you wont see much. something like this:

void loop()

{
       digitalWrite(5,HIGH);
       delayMicroseconds(1000);
       digitalWrite(5, LOW);
       delay(20);
   
       digitalWrite(5,HIGH);
       delayMicroseconds(2000);
       digitalWrite(5,LOW);
       delay(20);
}




if connected to the steering servo should go full left/right repeatedly if you have all the connections correct.

I don't think I am following you. If I don't use the pulseIn function, how do I read the receiver? Also, the whole point is to pass through the receiver data after I have had a chance to test some sensors to be sure that what is being requested by the receiver is an appropriate request.

Am I completely off the mark?

I thought I needed the PWM pins for DIO 5 and 6

But, you are just turning the pins on and off. No need to use a PWM pin for that.

but since I didn't need any other PWM pins, I didn't think it mattered.

It doesn't. The PWM pins are also digital pins.

Before, I was driving the sabertooth by hooking ch1 to S1 and ch2 to S2. That worked but did not allow me to run any logic against the output of the receiver. The whole point of this is to see if I can intercept the data from the receiver and make some decisions and tests against that data before passing it though to the sabertooth (or preventing it from passing through).

I was under the impression that the Sabertooth device had a serial interface.

If you use the Servo library and servo.writeMicroseconds you can measure the pulse width and directly output the servo signal or modify it and write it out. The signal automatically repeats at the 50 hz expected by the servo or ESC. And any digital pin can be used for a servo output, not just PWM pins.

Actually, I am not trying to just turn pins on and off. I am trying to pass through a pulse received from the RC receiver. I can not know in advance the duration of that pulse.

Yes, the sabertooth can use packetized serial and originally I was using that. I found that it was not nearly as responsive as just running the pulses from the receiver straight through to the sabertooth. Unfortunately, doing that, I gave up any external sensor information that would indicate what are and are not acceptable movements.

That is when I came up with what may turn out to be a hair brain idea. I wondered if I could intercept that pulse signal, testing against whatever criteria I want, and then either pass it through or not pass it through. This would give me the ability to inject my logic into the process and still maybe I could retain the responsiveness of the analog pulses.

The Goal here was more to see if I could do it. Certainly I could go back to the packetized serial...just wouldn't know if intercepting the analog signal is even possible

I have ordered another receiver that has SBUS capabilities, and that may be the answer, but I hate unanswered questions...even if the questions are not that vital.

groundfungus:
If you use the Servo library and servo.writeMicroseconds you can measure the pulse width and directly output the servo signal or modify it and write it out. The signal automatically repeats at the 50 hz expected by the servo or ESC. And any digital pin can be used for a servo output, not just PWM pins.

hmmm....that is certainly worth a try. Thanks for the suggestion.

crchisholm:
I don't think I am following you. If I don't use the pulseIn function, how do I read the receiver? Also, the whole point is to pass through the receiver data after I have had a chance to test some sensors to be sure that what is being requested by the receiver is an appropriate request.

the code i posted would do the two extremes, without passthrough - if this works, your connections are fine (ie: a test). if you can verify this works, you can then replace the delayMicroseconds() call with the values you receive from pulseIn() - the issue you have may be the fact your not sending the right PWM signals in the first place to be able to control the servos. the Servo library mentioned would also be an interesting avenue to explore

Got it! I will try it tomorrow. Right now, I am going to go back to bed and at least see if I can make that work.

I have ordered another receiver that has SBUS capabilities, and that may be the answer

I predict that it will be the source of more problems rather than providing the answer.

When I needed to extend the pulse width of an RC channel beyond what the transmitter setup provided I used this

  yawDuration = pulseIn(yawInPin, HIGH);
  yawDuration = map(yawDuration, 1000, 1800, 980, 2020);
  digitalWrite(yawOutPin, HIGH);
  delayMicroseconds(yawDuration);
  digitalWrite(yawOutPin, LOW);

Actually, I am not trying to just turn pins on and off. I am trying to pass through a pulse received from the RC receiver. I can not know in advance the duration of that pulse.

Please show me where you are doing anything other than turning pins on and off. That's all that the Servo library or PWM does.

PWM uses timers to toggle when the pin is on or off, rapidly enough that some devices connected to the pin will think that they are seeing a lower voltage.

The Servo library turns the pins on an off, too, with varying amounts of timing between the on and off transitions. It is that action that you are trying to replicate. As suggested, looking at how the Servo library manages that would be a good start. Or, just set the value for writeMicroseconds() to be a function of the time you get from pulseIn(), and don't worry about how the Servo class makes the magic happen.

Your only challenge will be to determine what the relationship between the pulseIn() value and the delayMicroseconds() value needs to be.

Please show me where you are doing anything other than turning pins on and off. That's all that the Servo library or PWM does.

Yah, I think maybe that was a dumb statement on my part. Of course your right. I was just thinking you meant I was trying to flip state from on to off or off to on as an isolated task. Sorry.