Using PWM sequence with Arduino Uno

Hello. I have a small project with Arduino Uno using PWM with two outputs.
Step 1:
I need to set output A to 5000Hz with DC=50% and output B to 100Hz with DC=50%.
Then I want to run these outputs in sequence. The sequence can be A for 4-5 seconds and then B for 10 milliseconds repeatedly.
Step 2:
I want to connect the Uno to a small keyboard and display to be able to change the values for frequency and times for the sequence.
I would be happy for any idea here.
Regadrs G.Lexau

Hi,
I didn't quite understand your requirement.
The idea you already have.
What exactly do you want?
A code, a schematic, etc. etc.?
The purpose of this forum is to help with difficulties and problems encountered in projects.
It's not writing code and drawing schematics.
Show your best effort, even if it doesn't work and we'll try to help as best we can.
BTW, you already read the thread:
How to get the best out of this forum ?

The "tone" function can do 5 kHz. Might be able to do 100 Hz.

So something like:

void loop()
{
  tone(PinA, 5000);
  delay(4500);  // 4.5 seconds
  noTone(PinA);
  tone(PinB, 100);
  delay(10);
  noTone(PinB);

Then change the four constants to variables, add the keypad and LCD, and use the keypad input to change the four variables.

1 Like

If you want 2 output pins then each pin goes to a distinct timer (timer 1 and 2).

If the signal is for one output pin only then use the TimerOne library.

The claim for tone() is

It is not possible to generate tones lower than 31Hz

so it looks like tone() would kill this.

a7

Hi John. Tried your code and it worked perfect. Attached is the oscilloscope snapshot of the two pins 9 and 10. Now I need to find a keyboard and display for this. Any suggestions ?
Regards Geir

Google.

Maybe this kind of thing

You didn't say how small a keyboard or how large a display, which leaves a huge range of possibilities for you user interface.

I also mention by mentioning it the EEPROM memelry available, where you might want to store the settings so they would be loaded next time as you set them last time.

a7

Like I said:

I have ordered 1602 LCD Keypad Shield For Arduino DFR0009 and will try it in a weeks time
Regards Geir

Hi John.
I have used the code you gave me earlier and it works fine.
I have another question , how can I change the four variables FreqA, FreqB, DelayA and DelayB in the 16x2 lcd with code ?

Attached code
#include <DFRobot_RGBLCD1602.h>

DFRobot_RGBLCD1602 lcd(16,2);
// Define keys
int lcd_key = 0;
int adc_key_in = 0;
int MenueHandle = 0;
int FreqA = 5000;
int FreqB = 100;
int DelayA = 4500;
int DelayB = 15;
int r=255; //Set red brightness (Range: 0-255)
int g=255; //Set green brightness
int b=0; //Set blue brightness

#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
#define PinA 9
#define PinB 10

int read_LCD_buttons() //Determine which button is pressed
{
adc_key_in = analogRead(0); // 0 read the ADC from analog values
// By setting different threshold, you can read the corresponding to the appropriate buttons
if (adc_key_in > 1000) return btnNONE;
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 250) return btnUP;
if (adc_key_in < 450) return btnDOWN;
if (adc_key_in < 650) return btnLEFT;
if (adc_key_in < 850) return btnSELECT;
return btnNONE;
}

int PulseHandle()
{
tone(PinA, FreqA);
delay(DelayA);
noTone(PinA);
tone(PinB, FreqB);
delay(DelayB);
noTone(PinB);
//lcd.setCursor(0,10);
//lcd.print(PinA);
}

int ReadButtons()
{
lcd_key = read_LCD_buttons(); // Read button content
switch (lcd_key) // Select to output content according to the pressed button
{
case btnRIGHT:
{
// lcd.print("RIGHT ");
break;
}
case btnLEFT:
{
// lcd.print("LEFT ");
break;
}
case btnUP:
{
// lcd.print("UP ");
break;
}
case btnDOWN:
{
// lcd.print("DOWN ");
break;
}
case btnSELECT:
{
// lcd.print("SELECT");
break;
}
case btnNONE:
{
// lcd.print("NONE ");
break;
}
}
}

void setup()
{
Serial.begin(9600);
lcd.init();
lcd.setRGB(r,g,b); //Set RGB
MenueHandle = 0;
pinMode(PinA,OUTPUT);
pinMode(PinB,OUTPUT);

}

void loop()
{
// lcd.setCursor(0,0);
// lcd.print("1234567891234567");
// lcd.setCursor(0,1);
// lcd.print("ABCDEFGHIJKLMNOP");
// delay(2000);
ReadButtons();
if (lcd_key > 0) {MenueHandle = 1;}
if (MenueHandle = 0) {PulseHandle();}
lcd.setCursor(0,0); //Set display output position
lcd.print(FreqA);
lcd.setCursor(10,0);
lcd.print(DelayA);
lcd.setCursor(0,1);
lcd.print(FreqB);
lcd.setCursor(10,1);
lcd.print(DelayB);
}

You could use the Left and Right buttons to select which digit to change and the Up and Down buttons to change the digit. You just need to decide which position on the display each digit appears. Looks like four digits per entry so 16 digits total. That leaves you 16 characters for labeling.

Hi John.
I have one more question for you : What is the best way to stop the 'PulseHandle' from running (by using the btnSelect ? I guess this has to do with the Delay() function that when I press the btnSelect it's working 'by chance' ?
Any suggestion here ?

#include <DFRobot_RGBLCD1602.h>

DFRobot_RGBLCD1602 lcd(16,2);
// Define keys
volatile int lcd_key = 0;
volatile int adc_key_in = 0;
volatile int MenueHandle = 0;
volatile int Handler = 1; // 1=FreqA, 2=FreqB, 3=DelayA and 4=DelayB
volatile int IncreaseF = 100;
volatile int DecreaseF = 100;
volatile int FreqA = 5000;
volatile int FreqB = 100;
volatile int DelayA = 4500;
volatile int DelayB = 15;
int r=255; //Set red brightness (Range: 0-255)
int g=255; //Set green brightness
int b=0; //Set blue brightness

#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
#define PinA 9
#define PinB 10

int read_LCD_buttons() //Determine which button is pressed
{
adc_key_in = analogRead(0); // 0 read the ADC from analog values
// By setting different threshold, you can read the corresponding to the appropriate buttons
if (adc_key_in > 1000) return btnNONE;
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 250) return btnUP;
if (adc_key_in < 450) return btnDOWN;
if (adc_key_in < 650) return btnLEFT;
if (adc_key_in < 850) return btnSELECT;
return btnNONE;
}

int PulseHandle()
{
tone(PinA, FreqA);
delay(DelayA);
noTone(PinA);
tone(PinB, FreqB);
delay(DelayB);
noTone(PinB);
}

int ReadButtons()
{
lcd_key = read_LCD_buttons(); // Read button content
switch (lcd_key) // Select to output content according to the pressed button
{
case btnRIGHT:
{
Handler++;
if (Handler == 5) {Handler = 1;}
break;
}
case btnLEFT:
{
break;
}
case btnUP:
{
if (Handler == 1) {FreqA = FreqA + IncreaseF;}
if (Handler == 2) {FreqB = FreqB + IncreaseF;}
if (Handler == 3) {DelayA = DelayA + IncreaseF;}
if (Handler == 4) {DelayB = DelayB + IncreaseF;}
break;
}
case btnDOWN:
{
if (Handler == 1) {FreqA = FreqA - DecreaseF;}
if (Handler == 2) {FreqB = FreqB - DecreaseF;}
if (Handler == 3) {DelayA = DelayA - DecreaseF;}
if (Handler == 4) {DelayB = DelayB - DecreaseF;}
break;
}
case btnNONE:
{
break;
}
case btnSELECT:
{
if (MenueHandle ==1) {MenueHandle =0;}
else
MenueHandle = 1;
}
}
}

void setup()
{
Serial.begin(9600);
lcd.init();
lcd.setRGB(r,g,b); //Set RGB
MenueHandle = 1;
Handler = 1;
pinMode(PinA,OUTPUT);
pinMode(PinB,OUTPUT);

}

void loop()
{
ReadButtons();
//if (lcd_key > 0) {MenueHandle = 1;}
if (MenueHandle == 0) {PulseHandle();}
//MenueHandle = 1;
lcd.setCursor(0,0); //Set display output position
lcd.print(FreqA);
lcd.setCursor(10,0);
lcd.print(DelayA);
lcd.setCursor(0,1);
lcd.print(FreqB);
lcd.setCursor(10,1);
lcd.print(DelayB);
lcd.setCursor(7,0);
lcd.print(MenueHandle);
lcd.setCursor(7,1);
lcd.print(Handler);
}

Hi, @lexgei
PLEASE;
To add code please click this link;

Thanks... Tom.. :smiley: :+1: :coffee: :australia:

Two problems: When calling PulseHandle() (MenuHandle == 0) the delays will make the button presses unresponsive because you only check the buttons every 9-ish seconds. When NOT calling PulseHandle() (MenuHandle == 1) the lack of delays will make the buttons TOO responsive and it will likely read the button more than once.

To fix the first problem you have to remove delay() and use millis() for timing. To fix the second you would use State Change Detection for the buttons and only act when the button changes from not-pressed to pressed.

Hi John. Thanks for the answer.
I will try it. I've even tried Threads but no joy.
Thanks a lot for you good advices.
Regards Geir.

Will this delay() block polling the Keypad?

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