2 pwm signals without delay

Hi
i made that:

int val = 0;
int val2 = 0;
int a = 0;
int b = 0;


void setup() {
 Serial.begin(9600);//Uruchomienie komunikacji przez USART
  pinMode(3, OUTPUT); //wyjscie
  pinMode(9, OUTPUT);
}

void loop() {
  val = analogRead(A5);
  float a = map(val, 0.0, 1023.0, 250, 1650) / 100.0;
 
  digitalWrite(3, LOW);
  delay(a);                
  digitalWrite(3, HIGH);
  delay(a);
 
  val2 = analogRead(A4);
  float b = map(val2, 0.0, 1023.0, 250, 1650) / 100.0;
 
  digitalWrite(9, LOW);
  delay(b);                
  digitalWrite(9, HIGH);
  delay(b);

  Serial.println(a);//Wysyłamy ją do terminala
  
}

but i don't know how to separate this 2 output signals
i need 2 outputs with 50-330hz controlled by analog potentiometer 10k ohm

Why are the delay() values floats when delay() takes an integer ?

As to your question about outputting 2 PWM signals at the same time

See Using millis() for timing. A beginners guide, Several things at the same time and the BlinkWithoutDelay example in the IDE

unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 1;  //the value is a number of milliseconds
int val = 0;
int val2 = 0;
int a = 0;
int b = 0;
void setup()
{
  Serial.begin(115200);  //start Serial in case we need to print debugging info
  pinMode(3, OUTPUT); //wyjscie
  pinMode(9, OUTPUT);
  startMillis = millis();  //initial start time
}

void loop()
{
  val = analogRead(A5);
  float a = map(val, 0.0, 1023.0, 250, 1650) / 100.0;
  val2 = analogRead(A4);
  float b = map(val2, 0.0, 1023.0, 250, 1650) / 100.0;
  
  currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
  if (currentMillis - startMillis >= a)  //test whether the period has elapsed
  {
    digitalWrite(3, !digitalRead(3));  //if so, change the state of the LED.  Uses a neat trick to change the state
    startMillis = currentMillis;  //IMPORTANT to save the start time of the current LED state.
  }
    if (currentMillis - startMillis >= b)  //test whether the period has elapsed
  {
    digitalWrite(9, !digitalRead(9));  //if so, change the state of the LED.  Uses a neat trick to change the state
    startMillis = currentMillis;  //IMPORTANT to save the start time of the current LED state.
  }
}

still something wrong :confused:

map does not return a float

You used the same startMillis variable for both pins.

1 Like
unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 1;  //the value is a number of milliseconds
int val = 0;
int val2 = 0;
int a = 0;
int b = 0;
int c = 0;
int d = 0;
void setup()
{
  Serial.begin(115200);  //start Serial in case we need to print debugging info
  pinMode(3, OUTPUT); //wyjscie
  pinMode(9, OUTPUT);
  startMillis = 1;  //initial start time
}

void loop()
{
  val = analogRead(A5);
  float a = map(val, 0.0, 1023.0, 250, 1650) / 100.0;
  val2 = analogRead(A4);
  float b = map(val2, 0.0, 1023.0, 250, 1650) / 100.0;
  
  c = millis();  //get the current "time" (actually the number of milliseconds since the program started)
  if (c - startMillis >= a)  //test whether the period has elapsed
  {
    digitalWrite(3, !digitalRead(3));  //if so, change the state of the LED.  Uses a neat trick to change the state
    startMillis = c;  //IMPORTANT to save the start time of the current LED state.
  }
    if (d - startMillis >= b)  //test whether the period has elapsed
  {
    digitalWrite(9, !digitalRead(9));  //if so, change the state of the LED.  Uses a neat trick to change the state
    startMillis = d;  //IMPORTANT to save the start time of the current LED state.
  }

}

again :frowning:

what mean "map does not return a float"? i dont know english so good

what is your mother-language?
Please tell us what is your native language?
Be the change you want to see in the world
best regards Stefan

this post is very helpfull THANKS

This is a text I wrote in German.

Then I had the text translated into English first.
And then the English text into Polish.

The grammar isn't great but it's easy to understand.
That's why I recommend you use google-translate if you don't speak much English
Write everything in Polish first and let google-translate translate the Polish text.

One or the other word will sound a bit strange
but you will understand. It is much better to be able to describe it in detail and to use a few unusual words in the translation than to write little. You will progress much faster in your project if you work with google-translate.

To jest tekst, który napisałem po niemiecku.

Potem najpierw przetłumaczyłem tekst na angielski.
A potem tekst z angielskiego na polski.

Gramatyka nie jest świetna, ale jest łatwa do zrozumienia.
Dlatego polecam korzystanie z google-translate, jeśli nie mówisz zbyt dobrze po angielsku
Napisz wszystko najpierw po polsku i pozwól google-translate przetłumaczyć polski tekst.

Jedno lub drugie słowo zabrzmi trochę dziwnie
ale zrozumiesz. O wiele lepiej jest umieć to szczegółowo opisać i użyć w tłumaczeniu kilku nietypowych słów, niż niewiele pisać. Jeśli będziesz pracować z google-translate, zrobisz postępy w swoim projekcie znacznie szybciej.

Be the change you want to see in the world
best regards Stefan

Some people must be beaten to their luck

Jak wspomniano wcześniej, funkcja map() używa

liczba całkowita

matematyka. Więc ułamki mogą zostać z tego powodu stłumione. Na przykład ułamki takie jak 3/2, 4/3, 5/4 zostaną zwrócone jako 1 z funkcji map(), pomimo ich różnych rzeczywistych wartości. Jeśli więc Twój projekt wymaga precyzyjnych obliczeń (np. napięcie z dokładnością do 3 miejsc po przecinku), rozważ unikanie map() i samodzielne zaimplementowanie obliczeń w swoim kodzie.

to samo z opóźnieniem

argument musi być typu

liczba całkowita

nie pływać

...

int stanLED1 = LOW;
int stanLED2 = LOW;
 
int val = 0;
int val2 = 0;
int a = 0;
int b = 0;
int c = 0;
int d = 0;
unsigned long aktualnyCzas = 0;
unsigned long zapamietanyCzasLED1 = 0;
unsigned long zapamietanyCzasLED2 = 0;
 
void setup(){
  Serial.begin(9600);
  pinMode(3, OUTPUT);
  pinMode(9, OUTPUT);

}
 
void loop(){
  //Pobierz liczbe milisekund od startu
  aktualnyCzas = millis();
 
  val = analogRead(A5);
  float a = map(val, 0, 1023, 500, 3300);
 val2 = analogRead(A4);
  float b = map(val2, 0, 1023, 500, 3300);
  c=a/100;
  d=b/100;
  
  if (aktualnyCzas - zapamietanyCzasLED1 >= c) {
    //Zapamietaj aktualny czas
    zapamietanyCzasLED1 = aktualnyCzas;
    //Zmieniamy stan diody na przeciwny
    stanLED1 = !stanLED1;
    //ustawiamy nowy stan na diodzie
    digitalWrite(3, stanLED1);
  }
 
    //Jeśli różnica wynosi ponad miganieLED2
  if (aktualnyCzas - zapamietanyCzasLED2 >= d) {
    //Zapamietaj aktualny czas
    zapamietanyCzasLED2 = aktualnyCzas;
    //Zmieniamy stan diody na przeciwny
    stanLED2 = !stanLED2;
    //ustawiamy nowy stan na diodzie
    digitalWrite(9, stanLED2);
  }
  Serial.println(d);
}

now working
but how can i get the frequency with more accuracy? so far I have jumps every 1ms

The map function does not return a float.

If you want better resolution, scale your values by 1000, and use micros() instead of millis()

Keep in mind each call to analogRead takes 100us or so

1 Like
int stanLED1 = LOW;
int stanLED2 = LOW;
 
int val = 0;
int val2 = 0;
int a = 0;
int b = 0;
unsigned long aktualnyCzas = 0;
unsigned long zapamietanyCzasLED1 = 0;
unsigned long zapamietanyCzasLED2 = 0;
 
void setup(){
  Serial.begin(9600);
  pinMode(3, OUTPUT);
  pinMode(9, OUTPUT);

}
 
void loop(){
  //Pobierz liczbe milisekund od startu
  aktualnyCzas = micros();
 
  val = analogRead(A5);
   a = map(val, 0, 1023, 5000, 32750);
 val2 = analogRead(A4);
   b = map(val2, 0, 1023, 5000, 32750);

  
  if (aktualnyCzas - zapamietanyCzasLED1 >= a) {
    //Zapamietaj aktualny czas
    zapamietanyCzasLED1 = aktualnyCzas;
    //Zmieniamy stan diody na przeciwny
    stanLED1 = !stanLED1;
    //ustawiamy nowy stan na diodzie
    digitalWrite(3, stanLED1);
  }
 
    //Jeśli różnica wynosi ponad miganieLED2
  if (aktualnyCzas - zapamietanyCzasLED2 >= b) {
    //Zapamietaj aktualny czas
    zapamietanyCzasLED2 = aktualnyCzas;
    //Zmieniamy stan diody na przeciwny
    stanLED2 = !stanLED2;
    //ustawiamy nowy stan na diodzie
    digitalWrite(9, stanLED2);
  }
  Serial.println(b);
}

Thank you very much for help. everything works.

The serial.print at 9600 baud does a substantial slow-down from 50-330 Hz to 17 - 80Hz.
With the serial.print removed the frequency range is still wrong
it has to be

  ADCval1 = analogRead (A5);
  period1 = map (ADCval1, 0, 1023, 1200, 10000);
  ADCval2 = analogRead (A4);
  period2 = map (ADCval2, 0, 1023, 1200, 10000);

Here is the corrected version in english

int LED1State = LOW;
int LED2State = LOW;

const byte freq1Pin = 3;
const byte freq2Pin = 9;

int ADCval1 = 0;
int ADCval2 = 0;
int period1 = 0;
int period2 = 0;
unsigned long currentTime = 0;
unsigned long rememberedLEDTime1 = 0;
unsigned long rememberedLED2Time = 0;

void setup () {
  Serial.begin (9600);
  pinMode (freq1Pin, OUTPUT);
  pinMode (freq2Pin, OUTPUT);

}

void loop () {
  // Get Number Of Milliseconds Since Startup
  currentTime = micros ();

  ADCval1 = analogRead (A5);
  period1 = map (ADCval1, 0, 1023, 1200, 10000);
  ADCval2 = analogRead (A4);
  period2 = map (ADCval2, 0, 1023, 1200, 10000);

  if (currentTime - rememberedLEDTime1 >= period1) {
    // Remember the current time
    rememberedLEDTime1 = currentTime;
    // We change the state of the diode to the opposite
    LED1State = ! LED1State;
    // we set the new state on the diode
    digitalWrite (freq1Pin, LED1State);
  }

  // If the difference is more than flashing LED2
  if (currentTime - rememberedLED2Time >= period2) {
    // Remember the current time
    rememberedLED2Time = currentTime;
    // We change the state of the diode to the opposite
    LED2State = ! LED2State;
    // we set the new state on the diode
    digitalWrite (freq2Pin, LED2State);
  }
  //Serial.println(b);
}

Be the change you want to see in the world
best regards Stefan

1 Like

Hello.
I don't know why but the program does not work as I need it.
The Pulse Generator module NE555 Impulsator 1Hz-200k works with a counter for which I wanted to use the arduino to get the range I am interested in - the range is too large in the module.

can it be the fault of the module I have between the arduino and the meter?
PWM controller - 400W 15A 36V - MOSFET ARDUINO ESP HW-517

Look around you. Are we there in the same room as you? No. Please remember that when you ask for help.

Post a schematic and links to the specs of all the important components including the meter, the PWM controller and the 555 module you refer to.

PWM Controller
ne555 module

Pulse Generator Module NE555
Supply Voltage: 5V - 15V
Chip: NE555
Maximum output current: 5mA with 5V supply and 35mA with 12V supply
Output amplitude: 4.2V PP - 11.4V PP
The range of the output frequency is selected by a jumper (from L to H):
1Hz - 50Hz
50Hz - 1kHz
1kHz - 10kHz
10kHz - 200kHz
Two potentiometers: frequency of the output waveform; fill factor.
Dimensions: 31mm x 22mm x 16mm (H)

the meter I wrote about is a car meter, and more precisely, a speed indicator and a tachometer

i need signal 50-330hz

it turned out that the meter accepts 5v :smiley: now arduino is enough for me. now I have to adjust the frequency ranges

@StefanL38
i need Your help :confused:

the output signal with respect to the analog input has a linear characteristic.
but it works badly
looks better to be a square characteristic
at the beginning the pointer rises slowly and at the end very quickly.
is there any possibility to change the characteristics?