VHF PTT Trigger for relay control

Hi, I used a Arduino UNO+ DTMF decoder (MT8870 circuit) + 2 Baofeng Uv5-re VHF radios + a 4-channel relay board to control some relays to turn lights on/off.

The radio has separate mic and audio inputs where my the speaker output is connected to the dtmf decoder do detect the tones being pressed.(works 100%)

and the mic input is connected to one of the 4 relays to make the "stationary baofeng" send an audio signal from my pc at my desire from a key (works 100%)

Now I want to have function where I can manually use the PTT button on the (handheld baofeng) radio to push 3 times for a relay to open, 3 times again to close a relay in example without the dtmf decoder as I belive the dtmf decoder doesn't detect the PTT button being pressed, it just opens for the keytones when you press and hold the PTT button.

How can I do this without using the dtmf decoder and detect the PTT button being keyed / pressed?

I believe that I need to wire the "stationary baofeng" speakers to arduino analog input and ground, but that signal is analog probably from 0-5V and needs to be biased.

Can someone draw a circuit diagram or something? I believe it has to be biased to max 2.5v or something like that.

I want to use a Y splitter jack so that I can both use the dtmf decoder functions to trigger a relay by keypad pressing and manually key PTT on the other radio to trigger a relay without pressing any keys.

Are you using this on an actual airfield? There are some extremely strict FAA requirements for this system.

Is this the same question as your previous topic?

wolframore:
Are you using this on an actual airfield? There are some extremely strict FAA requirements for this system.

Nope, this is my personal project. I have amateur radio license and can use FM and or VHF/UHF to control my lights somewhere else from my house. Here in my country they have moved to DAB since 2017 so most of the FM frequiencies are unused. The transmitting power is low and the antenna is small.

I think the lowest the Baofengs go is 1W.

srnet:
I think the lowest the Baofengs go is 1W.

It can also be put to 4W for VHF/UHF. I got a bigger antenna s the quality and range is ok.

Here is a test code I made just to turn on/off a relay by pressing the PTT button on the other radio and the stationary radio activates 1 relay as long as the PTT is pressed on the other one. I need some help coding further to making it turn the relay on after I press 3 times and stay on after some time or when I press 3 times again to turn the relay off.

const int R1 = 2; //Relay1 pin 2

int analogPin = 3; // PTT  analog input: analog pin 3 (PTT reading from radio operator).

int pttRead = 0; // Store PTT status from operator.

int pttPrevious = 0; // Store PTT state of previous loop (PTT release).

void setup() {  // Initializations.
  pinMode(R1, OUTPUT);  // Initialize digital pin R1 (pin R1 on Relay1)
  digitalWrite(R1, LOW);  // Initialize PTT: OFF
}

void loop() { // Main function, endless loop.

 delay(20); // 20 ms delay for "debouncing" PTT.

 pttRead = analogRead(analogPin);     // Read PTT input from radio operator.

 if (pttRead < 512) {  // If PTT is pressed.
     digitalWrite(R1, LOW);   // Activate the PTT on radio (turn on Relay1).
     pttPrevious = 1; // Goes to "1" if PTT has been depressed (memorizing PTT status).
 }

 if ((pttRead  > 512) and (pttPrevious == 1)) { // If PTT has been released by operator.
    

    pttPrevious = 0; // Re-initialize PTT state memorization.
    digitalWrite(R1, HIGH);    // Release PTT on radio transmitter (turn Relay1).
 }
}

As my previous post all that test code does now is to turn the relay on everytime I give signal by opening the radio's speaker output when I use the PTT button on the other radio on the same frequency (walkie talke style).

So as long as I press and hold the PTT button the relay is ON and if I release the PTT button the relay is OFF. But my goal is being able to just pres the button 3 times, after that the relay turns ON without me holding the PTT button pressed and then it can be turned off after amount of time using millis() if wanted.

It's similar to make a statement when to check if a button is pressed certain mount of times and the "led" turns on if the statement is true or keep the led off if the statement is false. But thats all digital inputs, so that is easier, but I am dealing with analog inputs and this is where I need some help coding that.

Well, to start with, when you detect a ptt activation, rather than setting a relay, just increment a global count variable. When it is three, set the relay and zero the variable.

wildbill:
Well, to start with, when you detect a ptt activation, rather than setting a relay, just increment a global count variable. When it is three, set the relay and zero the variable.

Can you write an example code?

I just figured out that my audio signal threshold when the PTT button is not pushed is about 477 which is 2.33 volts, and 684 which is 3.33 volts when the PTT button is pushed from the other radio.

This means that I constantly get an analog audio value about 477 from the radio's speaker 2.5mm jack and when I press the PTT my signal jumps to 684 which is normal behavior.

What are you using as an input circuit to the Arduino?

If this gives sufficient voltage, you use a digitalRead. :sunglasses:

Paul__B:
What are you using as an input circuit to the Arduino?

If this gives sufficient voltage, you use a digitalRead. :sunglasses:

Yes this seems nice. Basicly mine two upper rings of the jack was connected together (shorted) This is wrong as this will give the "AC" effect regardless how I triggered the PTT button it messed with the states as I noticed.

So to be able to test digitalread instead of analogread this time I put a 10k pullup resistor on the upper ring and connect to a relay input, then i connect the gnd ring (lowerst ring) to Arduino ground. After running a small "pushbutton" testcode with digitalread i managed to turn on and off the relay with digitalread which was my goal as digitalRead is easier to play code, just like the dtmf decoder :slight_smile:

I guess your circuit is a better circuit to protect the arduino input and forward bias it to 2.5V? peak to peak? Am I right?

I really cannot follow your description without a diagram. :astonished:

The circuit I have given is a peak-to-peak detector; it does not "bias to 2.5 V" but references to ground. If the audio signal is more than about 3.8 V peak to peak (2.5 V plus 1.2 V for the diode drops and a little more) it should register a HIGH on the input pin with a simple single digitalRead.

It does not include protection for the Arduino input but you would need to feed it 6.2 V or more to deliver more than 5 V to the Arduino pin. You could include a 10k resistor in series with the connection to the input pin if this was a concern. :grinning:

I see I see :slight_smile:

Regardless, it seems like a nice addition to what I did :slight_smile:

I can now control when the PTT button is pressed which seems to register a HIGH to the relay or a LOW to the relay without problems. Will post a new test code.

//constant value which will not change:
const int PTT = 6;
const int REL = 2;

//values will change:
int PTTState = 0;
int PTTPushCounter = 0;
int lastPTTState = 0;


void setup() {

pinMode(PTT,INPUT);
pinMode(REL,OUTPUT);
Serial.begin(9600);
Serial.println("PTT FUNCTION");

}

void loop() {
  // read the pushbutton input pin:
  PTTState = digitalRead(PTT);

  // compare the PTTState to its previous state
  if (PTTState != lastPTTState && lastPTTState == 0) {
    // if the state has changed, increment the counter
    if (PTTState == HIGH) {
      // if the current state is HIGH then the PTT went from off to on:
      PTTPushCounter++;
      Serial.println("on");
      Serial.print("number of PTT pushes: ");
      Serial.println(PTTPushCounter);
    } else {
      // if the current state is LOW then the PTT went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastPTTState = PTTState;


    
  if (PTTPushCounter % 4 == 0) {
    digitalWrite(REL, HIGH);
  } else {
    digitalWrite(REL, LOW);
  }
}

So here is a test code to make the PTT toggle relay with 4 PTT presses. (actually needs 3 to toggle the relay, the 4th press is alreday pressed?

The problem is that my relay is toggled right after i upload the code to arduino and I have to Press PTT to toggle it OFF, then I can toggle it by pressing PTT 3 times, and if I press 4th time it turns off. That is OK. But I dont want my relay to be toggled right after I upload the code.

I want it to stay OFF after I upload the code, then after pressing PTT 3 times the relay toggles ON, and then after I press 4th time it can turn off.

For those of you who dont know what PTT (Push-to-Talk) is, just imagine its now like a "button", but I actually press that "button" on the other radio through radio communication :slight_smile:

So basicly I need som help to fix this code

Since it is not the circuit I supplied, I want to know what circuit is actually connected to your "PTT" pin before I comment on the code. :roll_eyes:

Need a proper diagram. :astonished:


Alternatively:

  if (PTTPushCounter % 4 == 3) {
    digitalWrite(REL, HIGH);
  } else {
    digitalWrite(REL, LOW);
  }

Paul__B:
Since it is not the circuit I supplied, I want to know what circuit is actually connected to your "PTT" pin before I comment on the code. :roll_eyes:

Need a proper diagram. :astonished:


Alternatively:

  if (PTTPushCounter % 4 == 3) {

digitalWrite(REL, HIGH);
  } else {
    digitalWrite(REL, LOW);
  }

Will post a simple circuit as I draw one later. Thanks for the alternative, I just forgot to add == 3 on: if (PTTPushCounter % 4 == 3) instead of == 0 like I had it, must be my imagination going crazy but it works now without.

Anyway a circuit will be posted :slight_smile:

//constant value which will not change:
const int PTT = 6;
const int REL1 = 2;
const int REL2 = 3;
const int REL3 = 4;
const int REL4 = 5;

//values which will change:
int PTTState = 0;
int PTTPushCounter = 0;
int lastPTTState = 0;
unsigned long timeLastPush = 0;  //Millisek. since last time PTT was pressed..
unsigned long timeOutPTT = 8000; // 2,0sek


void setup() {

pinMode(PTT,INPUT);
pinMode(REL1,OUTPUT);
pinMode(REL2,OUTPUT);
pinMode(REL3,OUTPUT);
pinMode(REL4,OUTPUT);
Serial.begin(9600);
Serial.println("PTT FUNCTION");

}

void loop() {
  // read the pushbutton input pin:
  PTTState = digitalRead(PTT);

  // compare the PTTState to its previous state
  if (PTTState != lastPTTState && lastPTTState == 0) {  //If changed PTT state AND lastPTTState = 0, 
    if ((millis() - timeLastPush) > timeOutPTT ) {  //If timeout-limit for PTT reached:
  timeLastPush = millis();        //Set new timecouter start now,
  PTTPushCounter = 0;         //Set PTT counter to 0.
     } 
    // if the state has changed, increment the counter
    if (PTTState == HIGH) {
      // if the current state is HIGH then the PTT went from off to on:
      PTTPushCounter++;
      Serial.println("on");
      Serial.print("number of PTT pushes: ");
      Serial.println(PTTPushCounter);
    } else {
      // if the current state is LOW then the PTT went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastPTTState = PTTState;


    
  if (PTTPushCounter % 4 == 3) {
    digitalWrite(REL1, HIGH);
  } 
  if  (PTTPushCounter % 6 == 5) {
    digitalWrite(REL2,HIGH);
  } 
  if (PTTPushCounter % 8 == 7) {
    digitalWrite(REL3,HIGH);  
  }
  if (PTTPushCounter % 10 == 9) {
    digitalWrite(REL4,HIGH);
    } 
  else if (PTTPushCounter == 10) {
    digitalWrite(REL1,LOW);
    digitalWrite(REL2,LOW);
    digitalWrite(REL3,LOW);
    digitalWrite(REL4,LOW); 
  }
  }

This is now the updated test code.

Function: First: I have two radios UV-5r, one is used to transmit, the other is used to receive. I am not talking with the radios, just selected a free VHF channel and do PTT pushing thats all.

So the code works like this:

When I push ptt on the transmitting radio 3 times; 1st relay turns on .
When I push ptt on the transmitting radio 5 times; 2nd relay turns on.
When I push ptt on the transmitting radio 7 times; 3rd relay turns on.
When I push ptt on the transmitting radio 9 times; 4th relay turns on.
When I push ptt on the transmitting radio 10 times; All relays off.

My recieving radio has its speaker jack connected to the arduino with a 10k (pullup) resistor on the read pin (top pin). The speaker jack's ground pin is connected to ground on the arduino. And from the arduino a relay 4-channel relay board is also connected which is what i toggle.

So, Note that only the top ring and ground ring on the jack is connected to arduino with that 10k resistor. The middle ring is not connected.

Can someone help me with some better millis() delay code. So that If I toggle the first relay with my ptt transmitting radio, wait 5 mins or something and then it turns of the relay after that millis() delay ?

Thanks guys

Allright so I made a delay for when the relays will go off and thats fine, but I do have a problem.

The problem is that when I push the (button) 3 times, and only 3 times. The relay 1 goes off after the set interval using millis function, but it comes back on immediately instead of staying off after just after 3 pushes.

I have to push the 4th time to make it go off. which is not intentional for me at all.

the same thing happens if I push 5 times to toggle the relay 2, after the delay it comes back on immediately, meanwhile relay 1 is off due to I already pushed more than 3 times on the button just to be able to toggle relay 2.

I cant figure out what is wrong yet. Can someone help?

the code:

//constant value which will not change:
const int PTT = 6;
const int REL1 = 2;
const int REL2 = 3;
const int REL3 = 4;
const int REL4 = 5;

unsigned long interval = 30000; // interval at which to turn off a relay

//values which will change:
int PTTState = 0;
int PTTPushCounter = 0;
int lastPTTState = 0;


unsigned long previousMillis = 0; // will store last time a relay was updated.
unsigned long currentMillis = 0;
unsigned long timeLastPush = 0;  //Millisek. since last time PTT was pressed..
unsigned long timeOutPTT = 10000; // Timeout in milliseconds


DFRobot_LCD lcd(16,2); // Type of LCD display set 16 characters and 2 lines.

void setup() {
// initializing lcd
lcd.init();
  // start serial port for LCD
  Serial.begin(9600);
  Serial.println("PTT READY"); 
  lcd.setCursor(0,0);

  

//Pin configuration as connected by the schematic
pinMode(PTT,INPUT);
pinMode(REL1,OUTPUT);
pinMode(REL2,OUTPUT);
pinMode(REL3,OUTPUT);
pinMode(REL4,OUTPUT);
Serial.begin(9600);
Serial.println("PTT READY");

}

void loop() {
  // read the PTT input pin:
  PTTState = digitalRead(PTT);
  


  // compare the PTTState to its previous state
  if (PTTState != lastPTTState && lastPTTState == 0) {  //If changed PTT state AND lastPTTState = 0, 
    if ((millis() - timeLastPush) > timeOutPTT ) {  //If timeout-limit for PTT reached:
  timeLastPush = millis();        //Set new timecouter start now,
  PTTPushCounter = 0;         //Set PTT counter to 0.
     } 
    // if the state has changed, increment the counter
    if (PTTState == HIGH) {
      // if the current state is HIGH then the PTT went from off to on:
      PTTPushCounter++;
      Serial.println("PTT PUSHED");
      Serial.print("NUMBER OF PTT PUSHES: ");
      Serial.println(PTTPushCounter);
    } 
    }
    // Delay a little bit to avoid bouncing
   delay(50);

  // save the current state as the last state, for next time through the loop
  lastPTTState = PTTState;

  
  
   if (PTTPushCounter  %4 == 3) {
    lcd.clear();
    lcd.setCursor(3,0);
    lcd.print("RELAY 1 ON!");
    digitalWrite(REL1, HIGH);
    }
          
  if  (PTTPushCounter  %6== 5) {
        lcd.clear();
    lcd.setCursor(3,0);
    lcd.print("RELAY 2 ON!");
    digitalWrite(REL2,HIGH);
  } 
  if (PTTPushCounter   %8== 7) {
        lcd.clear();
    lcd.setCursor(3,0);
    lcd.print("RELAY 3 ON!");
    digitalWrite(REL3,HIGH);  
  }
  if (PTTPushCounter   %10== 9) {
        lcd.clear();
    lcd.setCursor(3,0);
    lcd.print("RELAY 4 ON!");
    digitalWrite(REL4,HIGH);
    } 
      
    

currentMillis=millis();

  if ((currentMillis - previousMillis) >= interval) {
    // saves the last time we turned the relay on/off
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("ALL RELAYS OFF!");
    digitalWrite(REL1,LOW);
    digitalWrite(REL2,LOW);
    digitalWrite(REL3,LOW);
    digitalWrite(REL4,LOW);
    
    previousMillis = millis();
    Serial.println(previousMillis);

  } 
  

    
}

Paul__B:
Since it is not the circuit I supplied, I want to know what circuit is actually connected to your “PTT” pin before I comment on the code. :roll_eyes:

Need a proper diagram. :astonished:


Alternatively:

  if (PTTPushCounter % 4 == 3) {

digitalWrite(REL, HIGH);
 } else {
   digitalWrite(REL, LOW);
 }

Here is a link I made on how the PTT wire from the radio to the arduino input and ground is connected. I measured about 3.7V, and using voltage divider circuit I manange to reduce the voltage to ~ 2.5V coming to the PTT read pin on the Arduino UNO input.

Circuit with Falstad