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

SamGibson
18.5k5 gold badges42 silver badges65 bronze badges
asked Aug 14, 2019 at 8:11
\$\endgroup\$
5
  • \$\begingroup\$ I can't see anything like interrupt in your code! \$\endgroup\$ Commented Aug 14, 2019 at 8:14
  • 1
    \$\begingroup\$ See reference for analogWrite(). It basically changes the duty cycle, not frequency. \$\endgroup\$ Commented Aug 14, 2019 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\$ Commented Aug 14, 2019 at 8:29
  • \$\begingroup\$ Do you want to make the timers in software or in hardware? \$\endgroup\$ Commented Aug 14, 2019 at 9:05
  • \$\begingroup\$ I think it would be best in the software \$\endgroup\$ Commented Aug 14, 2019 at 9:18

2 Answers 2

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.

answered Aug 14, 2019 at 10:58
\$\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\$ Commented Aug 14, 2019 at 11:46
  • \$\begingroup\$ @Neamus: I've added an explanation of the example. \$\endgroup\$ Commented Aug 14, 2019 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.

answered Aug 14, 2019 at 9:44
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.