0
\$\begingroup\$

I’m trying to get an Arduino to output 2 signals with different frequencies for a project.The schematic of the circuit is shown below.

I’m trying to experiment using Pulse Width Modulation to give me a constant signal (the code is similar to dimming an LED). Long story short, when the Arduino powers on the LED connect to ~9 flashes at a constant frequency (I still need to find out the frequency using a scope) and ~10 doesn’t flash at all. Once the button is* pressed* ~9 stops blinking, ~10 blinks for 30ms and ~9 starts blinking again.

So, my question is there a way I can get 2 signals to be outputted from an Arduino and somehow adjust the frequency of one of the outputs by changing a number (like ‘freq (1000)’ for 1 kHz).

Thank-you to all in advance.

//le code

int frequency = 0;
int milli = 10;
int milli2 = 30;
const int button = 2; 

int buttonState = 0;  

void setup()
{
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop()
{
  buttonState = digitalRead(button);
  for (frequency = 0; frequency <= 255; frequency += 127) {
    analogWrite(9, frequency);
    delay(milli); // Wait for 30 millisecond(s)
 }
  for (frequency = 255; frequency >= 0; frequency -= 127) {
    analogWrite(9, frequency);
    delay(milli); // Wait for 30 millisecond(s)
  }

   if (buttonState == LOW) {
    for (frequency = 0; frequency <= 255; frequency += 127) {
      analogWrite(10, frequency);
      delay(milli2);
 }
     for (frequency = 255; frequency >= 0; frequency -= 127) {
    analogWrite(10, frequency);
    delay(milli2); 
    } 
   }
  }

Schematic

\$\endgroup\$
5
  • \$\begingroup\$ I can't see anything like interrupt in your code! \$\endgroup\$
    – Long Pham
    Aug 14 '19 at 8:14
  • 1
    \$\begingroup\$ See reference for analogWrite(). It basically changes the duty cycle, not frequency. \$\endgroup\$
    – Long Pham
    Aug 14 '19 at 8:18
  • \$\begingroup\$ @LongPham I just had a look at it, are there any other functions that I can use for example state a pin and adjust the frequency of a signal? \$\endgroup\$
    – Neamus
    Aug 14 '19 at 8:29
  • \$\begingroup\$ Do you want to make the timers in software or in hardware? \$\endgroup\$
    – Paul
    Aug 14 '19 at 9:05
  • \$\begingroup\$ I think it would be best in the software \$\endgroup\$
    – Neamus
    Aug 14 '19 at 9:18
2
\$\begingroup\$

The better way to do this is to use timers.

The easiest way is to use a library that wraps up all the interrupt stuff for you, like the Timer1 library.

That library wraps all the details needed to set the interrupts and switch the outputs. It can also be used on various members of the Arduino family.

You can operate the two PWM pins at different rates.

Example:

#include <TimerOne.h>

#define SIGNAL_OUT_PIN 9

void setup() {
  pinMode(SIGNAL_OUT_PIN, OUTPUT);
  Timer1.initialize(1000);
  Timer1.pwm(SIGNAL_OUT_PIN,512,1000);
}

Just setup another output pin at the same time.


The whole complexity winds up behind one line:

Timer1.pwm(SIGNAL_OUT_PIN,512,1000);

That says "on pin 9 set a 50% duty cycle PWM at a period of 1000 microseconds repeat rate."

I defined "SIGNAL_OUT_PIN" as 9 earlier in the code.

The duty cycle is set in steps from 0 to 1023. 512/1023 is as close to 50% as you can reasonably get.

The period is set as microseconds. 1000 microseconds is 1 millisecond - that's 1kHz.

\$\endgroup\$
2
  • \$\begingroup\$ I just went on the definitons for the timer1 library, and i just wanted to know what this line means: Timer1.pwm(SIGNAL_OUT_PIN,512,1000); \$\endgroup\$
    – Neamus
    Aug 14 '19 at 11:46
  • \$\begingroup\$ @Neamus: I've added an explanation of the example. \$\endgroup\$
    – JRE
    Aug 14 '19 at 12:21
1
\$\begingroup\$

You can fix this in hardware or in software. Software is more portable as other Arduino boards will be able to run it as well. In hardware, you'll have to check the Atmega328P datasheet, to see how to set up the timers. And thus your code will only work on that MCU. Though it will be more accurate and faster.

Consider the following "pseudocode" for a software solution (writing on phone, so formatting/outlining may be awful).

limitA = 10;
limitB = 20;
timerA = 0;
timerB = 0;

loop(){
  timerA++;
  timerB++;
  if timerA > limitA
    digitalWrite(9, !digitalRead(9));
    timerA = 0
  if timerB > limitB
    digital write(10,!digitalread(10));
    timerB = 0
}

Basically you have two timers that run to a maximum value (change this to change the frequency) and then flip the pin status (on to off, off to on). In this way you get a 50% duty cycle with different frequency "factor" per pin.

Do mind that the frequency may vary a bit, especially since digitalWrite and digitalRead aren't specifically fast. It may also drift a bit over time. Also, if you add more logic to the program, the maximum frequency of this part will drop. If you add a "delay" anywhere, this part will basically halt.

If you're thinking of running multiple other parts of program, you could offload this part in hardware.

Also, there's some optimizations possible, as using a boolean to keep track of the pin state instead of digitalRead. Or using port manipulation instead of digitalWrite.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.