Toggling a pin ON-OFF at a 500 hz rate, able to change rate on the fly

I am looking for a possible way of toggling a Arduino pin on-off at a 500 to 1000 hertz rate, to produce a Symmetrical square wave. TimerOne will work for pwm, but I'm not interested in pwm. Also to change the frequency on the fly to what ever is desired. Is there a way to do this? I need some guidance on this to point me in the correct path forward.
Unlike

Check out the tone function.

https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/

1 Like

cattledog
Thanks, I must have overlooked this possibility of using tone.
I' try it out.

Doesn't the tone() function block? Never used it but I thought it did.

Try this. Uses a pot on A0 to adjust the rate. Not tested but at least it compiles :slight_smile:

const int DELAY_ADJ_FACTOR = 100;
const int BASE_DELAY_US = 500;

void setup() 
{
    // put your setup code here, to run once:
    pinMode(2, OUTPUT);
    digitalWrite(2, HIGH);
}

void loop() 
{
    float totalDelayTime = 0;
    float ts = 0;

    // Pin LOW
    digitalWrite(2, LOW);

    // Begin compensation for analog read time
    ts = micros();

    // Get delay adustment (0 - 102)
    int v = analogRead(A0) / DELAY_ADJ_FACTOR;
    
    // 500 us delay accounting for analog read time and adjustment value
    totalDelayTime = BASE_DELAY_US - v  - (micros() - ts);
    
    // Make sure it doesn't underflow
    totalDelayTime = totalDelayTime < 1 ? 1 : totalDelayTime;
    delayMicroseconds(totalDelayTime);

    // Pin HIGH
    digitalWrite(2, HIGH);
    delayMicroseconds(totalDelayTime);
}
1 Like

tone() is non blocking, even with a duration.

1 Like

Oh, well, forget my code then. Tone would be a better way to handle it.

1 Like

I tried Tone, Tone did generate a square wave signal, but it was not consistent the pulse rate jumped around. used an Oscope to see waveform. I tried two different processors a Leonardo and a pro mini getting the same results. the desired waveform was 180cps, it varied by as much as 20 cps. The Fluctuations must be due to processor execution of functions in my program. attached is the code that I used, I'll try something else that is more stable, but not easily changed.
Test_1_to_16.ino (1.5 KB)

Would this work?

You'll need it install LC_baseTools from the Arduino library manager to compile it on your machine.

-jim lee

It's always best to post your code inline. More people will see it without the download process involved.


#include <SPI.h> 
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <ContinuousStepper.h>
#include <ContinuousStepper/Tickers/Tone.hpp>

byte mac[] = {
  0xDE, 0xAC, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 15, 177);
unsigned int localPort = 8000;  
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; 
char ReplyBuffer[] = "acknowledged";
EthernetUDP Udp;
ContinuousStepper<StepperDriver, ToneTicker> stepper;
String disc = "";
String diss = "";
int pulsex = 100;
int pulsey = 100;

void setup() {
 Ethernet.init(10);
  stepper.begin(/*step=*/9, /*dir=*/A0);
  SPI.begin();
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);
  //Serial.begin(9600);
  stepper.spin(pulsex);
}

void loop() {
   stepper.loop();
  updRec();
  stepper.spin(pulsex);
  
}


void updRec() {
  
  int packetSize = Udp.parsePacket();
  if (packetSize) {
     Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
     disc = packetBuffer;
     disc.trim();
     
    if(disc.endsWith("PX")){
      pulsex = disc.toInt();
      udpTrans();
      }
    if(disc.endsWith("PY")){
      pulsey = disc.toInt();
      udpTrans();
      }
    if(disc.endsWith("Ss")){udpTrans();}//Remove after testing
    disc= "";
    } 
}




void udpTrans () {
  
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    if(diss.length() > 0) {Udp.println(diss);}
    if(disc.length() > 0) {Udp.println(disc);}
    Udp.endPacket();
    disc = "";diss = "";
}

Did you try the code I posted to see if it's more accurate?

I like your code it runs at 904Hz + or - 2 cps with a delay of 15, much closer to what I want to use. I didn't use an analog pot for DELAY_ADJ, I used the ethernet UDP interface to adjust the DELAY_ADJ and the BASE_DELAY_US. By adjusting the BASE_DELAY_US the frequency could be change from 500 @ 904 hz, to 210 hz @2300. seems to work pretty much okay, nice coding. You must have been a Math guy in school. Only one problem something seems to corrupt the UDP comm after running the code for a while, while changing the frequencies.

The Audio tone jumps around(20 cps) as much as the other tone for steppers

Thanks for the feedback. Not sure what's going on with UDP.


CedarlakeInstruments,
your code can do this , with a few changes
Thanks again!

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