How to fix a value

Here is a piece of code I am using;
if(digitalRead(pin)==HIGH && state==LOW){
delayMicroseconds (us);
delayMicroseconds (9000-us);

This code works perfectly when that is the only thing in the void loop. However I have more program after this. What I can see is happening is when the additional program is running this code is ignored. So for the very brief time the rest of the code is running the piece of code shown is ignored. The serial print is showing the correct value of us as 4500.
How could I fix the 'us' variable? It is no good changing 'us' to 4500 because the code is still going to be ignored while the rest of the program runs.

This delay freezes other code execution until the period is over.

This is referred to as blocking code.

How and Why to avoid blocking code:

Demonstration code for several things at the same time.

When that is the only code in the loop, with us of 4500, ledPin will be HIGH for 4500uS, and LOW for a bit over 4500uS, roughly a 50% duty cycle. When you add additional code, it is likely extending the time that ledPin is LOW, making the percentage of time it is HIGH much less, depending on how long the additional code takes. If HIGH turns on an LED, and the additional code takes a long amount of time, you will likely never see the LED light for 4500uS.

I don't know what you are trying to do with that pin, but it looks like a task for hardware PWM. You can set the frequency to 122.55 Hz, which is pretty close to the 111.11 Hz you are after. This will work on pins 3, 9, 10, 11 and the timing will be more precise than your solution, because it is done in hardware and without the overhead of the heavy digitalWrite() function. Look here.

Hi, @petercl14
What is the application?
Can you please post your complete code, in code tags?
Please press < CTRL > < T > in the IDE to autoformat your code before posting in a NEW post.

Where do you set the value of "us"
Some meaningful variable names might also help.

To add code please click this link;

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

The analog out pins on my nano board are numbered AO-A6. So I think what you are saying is to use these pins. In the coding here 255 is a 5v output and 0 is 0v output. Any particular desired output voltage is given by analog write x where (x/255)*5 =output voltage. And if this is run by built in hardware on the board no software will change this output voltage unless of course you change x.
In other words the analog out will be running concurrently with the rest of the programming and independently of it. Is that a correct statement?

looks like the posted code takes 10 msec.

is delaying any other code by 10 msec that critical?

what is the purpose of the pulse being generated? is it a single pulse or cyclic? can a PWM output be used?

I am going to try something else without the delay. Look at my reply to someone else on the forum. If it works I think it is called multi-tasking.

multi-tasking usually describe multiple independent programs running using an operating system

a single program can certainly invoke multiple functions triggered by various events such as digital inputs, analog thresholds being crossed or timers expired.

of course multiple functions, just like tasks with an OS affect (i.e. delay) one another. the choice of approaches depends on the how much delay is tolerable and which function/task is most critical

what resolution does your pulse require? could millis() be used or does it really require sub-msec resolution?

Those are analog INPUT pins. Most arduino boards do not have any analog output pins, only PWM (pulse width modulation pins).

No this is not how it works. Probably, like many people, you are confused by the silly name of analogWrite(): it should really be called pwm_write() or something like that. Boards like the Nano do not have true analogue output: they have pulsed width modulation. At any given instant in time, the output is either 0v or 5v.** Depending on how much time the square wave spends in the low or high state (this is the duty cycle), the average voltage over time appears to be higher or lower. An LED will seem to be dimmer or brighter because our eyes aren't fast enough to see the flicker; a DC motor will spin faster or slower because the inertia of the rotor will smooth up the motion; and so on.

The other parameter of PWM, apart from duty cycle, is the frequency: how many times in a second the square wave repeats itself.

To change the duty cycle, you pass a parameter to [sigh!] analogWrite().

To change the frequency, you set some registers, like in the link.

** If we pretend that the square wave is mathematically square and the rise time is instantaneous, which is of course an approximation of what happens in a real circuit.

my mistake. they measure an analog voltage input

I think I have the solution now. You are saying pwm is being run with hardware on the mega 328p which is the microcontroller being programmed on my nano board. pwm is set by the analog write function. 255 will give a 5v output and 0 a 0v output. So if I use analog write instead of digital write including the delay this will be running independently of what any software may be doing in the background?
I believe this is what the example sketch in arduino 'analog write mega' is doing with the leds.
If you use digital write and have additional programming in your sketch the digital write function ceases for the time the additional programming is running. This is showing up in my meter reading which does not show a steady voltage anymore.

I have now tried this program which uses analog write instead of digital write;
void loop() {
if(digitalRead(pin)==HIGH && state==LOW){
delayMicroseconds (4500);
delayMicroseconds (4500);

The result is exactly the same. You have said that pwm is run by hardware. Again while this programming works ok when run on its own, when additional programming is added it fails again. If hardware was running this it should make no difference when the program is redirected to other parts. Analog write is pwm.
Again when the additional programming is run the above program is ignored for the running time of the extra programming. You can see the difference in the output voltage reading. If the pwm was hardware run that shouldn't happen.
Have you seen in the specs of the atm3028p that they have this hardware on the chip? If that is the case then my nano board may not have included it.

It looks like the hardware pwm is not included on my nano board which uses the atmega 328p chip. Refer to the example sketch 'analog write mega'. Here it says this sketch can only be used with the arduino mega board which uses a different microcontroller. On this chip must be the hardware pwm missing on the 328. I guess you had assumed that the 328 had this hardware.
This is a nuisance. So I can either get this board or find another way with the nano.

No. There is no way you can run anything that includes delay() independently of anything else. While the µC is in delay, it can only wait and do nothing else.

If you write blocking code (which you did), you can only run one thing at a time, no matter what thing you are running.

Of course it is: you are still using delays. What did you expect?

PWM itself is run by hardware. This doesn't mean you can magically run code in parallel just because you made a call to analogWrite().

This can't possibly be true. From the 1st page of the datasheet:

● Six PWM channels

If you don't believe me and if you don't trust the datasheet, look at the output of analogWrite() for yourself with an oscilloscope.

From the beginning of this thread, I thought you were trying to emulate a PWM signal in software. It is better, however if we take a step back.

What are you trying to achieve with your program?

Hi, @petercl14

What is your application, and do you need an exact frequency of your PWM signal?

That is not how you get PWM from analogWrite.
You might better to go back to basics and understand each function you want to use.

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

the application is phase control of the mains voltage. the analog write or digital write connects to a random phase triac optocoupler which triggers a triac. you have to set the off/on times at zero crossing of the mains voltage. The code is measuring a high going pulse at zero crossing. I made the hardware for doing this. After zero crossing the hardware give a zero voltage for the rest of the mains voltage until it goes 5v high at the next zero crossing of the mains voltage.
The program on its own works perfectly. For instance if you have a filament globe attached to the triac it dims down at 4500us and when measuring the ac voltage you get approx half the mains voltage and there is no flicker in the filament globe.
It all goes crazy when I add additional programming to the sketch. The globe flickers and the ac reading is all over the place. I put this down to the 4500 code being ignored while the program traverses the additional programming. The additional programming does not contain any delays or anything like that so it should be skipped over very rapidly. I am thinking that a faster speed on the microprocessor would fix the problem .
My nano has 16mhz. There are much faster processors as in the nano 33 at 64mhz.


Which means your project is very time sensitive.
Using delays that blocks and then adding extra code that takes extra time, your loop time is getting longer and longer, you are probably missing the zero crossing signals.


arduino ac dimmer tutorial

Here is a simple example with description.

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

1 Like

I believe the time has come to post the whole program and a schematic of the hardware, just to see what is supposed to do what.