Hot answers tagged

34

The PWM signal is generated by timers on the AVR chips. Each timer can generate a PWM signal on two or three different pins. Each pin can have it's own duty cycle, but they share the PWM frequency. You can change the frequency of the PWM by changing the clock source for the timers. By default they use the CPU clock divided by 64, ie. they have their ...


24

Those aren't the only frequencies available for the PWM signals. However, they are the frequencies as determined by the applied prescaler (which you can readily change as detailed below). Each of the 3 pairs of PWM pins is tied to one timer, each of which has its own base frequency, as follows: Pins 5 and 6 are paired on timer0, with base frequency of ...


20

You can get pretty close if you program Timer 1 directly (not through the library), and have it run with the prescaler set to 1. Ideally, you want the period of the timer in clock cycles to be: F_CPU / 15 kHz = 16,000 kHz / 15 kHz ≈ 1066.67 CPU cycles If you round this to the nearest integer, you get F_CPU / 1,067 = 16,000 kHz / 1,067 ≈ 14.9953 kHz This is ...


17

The Arduino Uno is based on an ATmega382P microcontroller. This chip has two 8-bit timers, driving two PWM channels each, and one 16-bit timer, driving the last two channels. You cannot increase the resolution of the 8-bit timers. You can, however, put the 16-bit timer in 16-bit mode, instead of the 8-bit mode used by the Arduino core library. This will ...


13

You can configure Timer 1 to cycle at 25 kHz in phase correct PWM mode, and use it's two outputs on pins 9 and 10 like so: // PWM output @ 25 kHz, only on pins 9 and 10. // Output value should be between 0 and 320, inclusive. void analogWrite25k(int pin, int value) { switch (pin) { case 9: OCR1A = value; break; ...


13

At first you had the scope AC (Alternating Current) coupled. Then you switched it to DC (Direct Current) coupled. AC coupling is used to remove the DC component of a signal. It places a large capacitor between the probe and the internal amplifier. This is used, for instance, if you want to see a small signal with a large DC offset. But it can also ...


12

I am posting this second answer since I realized it is possible to have 4 PWM channels at 25 kHz with 161 steps on a single Arduino Uno. This involves changing the main clock frequency to 8 MHz, which has some side effects since the whole program will run half as fast. It also involves reconfiguring the three timers, which means loosing the Arduino ...


12

You basically have three options: Switch to an Arduino Due which has a built-in DAC which outputs a real voltage. Add an external DAC chip (such as the MCP4821/2) to create the voltage for you Use a low-pass filter (R-C network) on a PWM pin. Of the three options I usually use an MCP4822 since it gives the best results and doesn't cost as much as using a ...


11

The pulsein() function is very lossy, in that it is a hard loop and returns a number * the assumed clock cycles it takes for per loop ... // wait for the pulse to stop while ((*portInputRegister(port) & bit) == stateMask) { if (numloops++ == maxloops) return 0; width++; } // convert the reading to microseconds. The loop has been determined // ...


11

Section 16, "16-bit Timer/Counter1 with PWM" of Atmel-8271J-AVR- ATmega-Datasheet_11/2015 describes using Timer/Counter-1 for 16-bit PWM, including sample code in both C and assembler. It might take a couple of reads over that section to get familiar with the hardware and learn what else T/C-1 is used for, and that you might have to give up while using it ...


9

Pin 11 is shared between both PWM and SPI. By activating SPI you've disabled PWM from working on that pin. Either use another PWM pin instead, or switch to software SPI on different pins.


9

The simplest way is to change your value range to 0-255. You can't change analogWrite's range, since that is fixed in the core software. analogWrite(5, val >> 2); The >> 2 bit-shifts the value two bits to the right, turning a 10-bit value (0-1023) into an 8-bit value (0-255). It's by far the most efficient way of dividing by 4. On more complex ...


9

Since the timer1 library only accepts whole numbers for the µs parameter you get a error. You could skip using the library and configure the timer directly. Or you could have a look at the source code of the library, and see that you can kind of bypass the limitation it has by only calculating a more accurate value for the ICR1 register. Look at cycles = ((...


8

I am not aware of the design considerations, but if you check the datasheet for the microcontroller on your Arduino, you will notice that PWM pins are grouped together and per group connected to a timer. The speed at which this timer is increased varies by the configured prescaler. If you change the prescaler for a certain timer, you change the PWM frequency ...


8

Analog read is 10-bits (2^10 = 0-1023 range), analog write is 8-bits (2^8 = 0-255 range). Ditch the lower two bits of the result either by doing: analogIn = analogIn >> 2; which can be shortened to: analogIn >>= 2; Or you can use the rather complex map function: analogIn = map( analogIn(0, 1023, 0, 255) )


8

Is PWM really a signal? To me, it looks like an electric current turned on and kept on for a certain time, then off for a while repeatedly. What makes this a "signal"? At the most basic, it is a signal because we call it such. Even a constant voltage can be a signal, signalling that e.g. a window has not been broken. A PWM signal indicates that we want to ...


7

It's... mostly wrong. For three independent reasons. The LEDs themselves, like all diodes, absorb some of the electrovoltaic potential of the electricity passing through them, resulting in a voltage decrease in their circuit. This means that although 5V is being used to power the resistor and LED in a circuit, only some of that voltage is passing through ...


7

You seem to have misunderstood PWM here. It's actually a digital signal which is constantly pulsing on and off very quickly (several hundred times per second). You don't actually change the output voltage at all -- it's only ever HIGH or LOW (+5v or +0v). The thing you change is how long the signal is HIGH for on each pulse. This page gives a deeper ...


7

Yes, you can do this with "a little programming" or more easily by adding two cheap components. If you connect a say 47k resistor from PWM_Out to Analog_In and a say 100 uF capacitor from Anaolg_In to ground you will be able to read the equivalent analog value to an accuracy of around 1%. Read it N times (maybe 10 times) with a delay of say 12 ms between ...


7

At 5V, a 1 ohm resistor will try to sink 1A and far exceed the 40mA specs. Please use at least a 5/0.040=125 ohm resistor to protect your pin. And if you put the a capacitor between your resistor and ground, the RC circuit of the capacitor will smooth out the PWM into an analog voltage. Please try the suggested @russell answer with a 47K resistor and ...


7

First: Why would you need to measure the PWM value. You already know it; it's saved in the val variable. Why not just use this variable for later use in code? Second: Doing the analogRead on the same pin as the PWM output is not going to work. Internally there are 2 different hardware peripherals, that are responsible for these functions: The ADC is ...


7

A better way to do the above average 15 kHz (or any other frequency) is with a phase accumulator scheme. There are no IF tests; on each tick of an interrupt, you add a step to an accumulator and output the state of its MSB. This can give incredible resolution, and is probably the best you can do. But though the average frequency will be dead-on, the ...


6

You don't need the MOSFET, you don't need the capacitor, you do need the resistor. The pins on your Arduino can deliver up to 20mA comfortably, so in this case there is no need for the MOSFET. However, if you were to replace your backlight with a high power LED, your current setup will work just fine. Without a capacitor, your PWM is a nice square wave. ...


6

They do not conflict as millis() strictly reads the immediate value in TCNT0 whereas PWM via timer 0 uses the hardware's ability to compare the value of TCNT0 with the values in OCR0x without affecting the value of any of them.


6

This is a common arrangement and is known as Common Anode, and the I/O pin is said to be sinking current. To better understand what is happening here it's best to think of an I/O pin as a two-position switch: When the I/O pin is HIGH point 1 is connected to point 2. When the I/O pin is LOW point 1 is connected to point 3. So when HIGH the circuit is Vcc ->...


6

I agree with @Majenko's answer, though here is a more "beginner" friendly method of doing the same. val = map(val,0,1023,0,255); analogWrite(pin, val); Not the most efficient, but still...


6

It is very simple to set up a PWM signal at any frequency you desire, with any resolution you desire, provided you don't exceed the maximum 'bandwidth': the frequency multplied by the resolution must be less than half the clock speed of the device. The full explanation with relation to the ESP-IDF is available here. The article explains the intricacies of ...


6

I advice you to learn about basics of how to connect external components to MCU. Anwser to your question is simple transistor amplifier... So you can use bipolar transistor (NPN/PNP) or MOSFET... MOSFETs is better for switching like your case, switching via PWM. If you switching inductive load with MOSFET like motors or coils, don't forget add antiparallel ...


6

This line: TIMSK = (1<<OCIE1A) | (1<<TOIE1); enables a couple of interrupts generated by Timer 1. Whenever you enable an interrupt source, you should make sure that the matching ISR has been defined. Otherwise, the interrupt request is routed to __bad_interrupt(), which by default jumps to the reset vector, thus resetting your program.


6

That is how it is supposed to be. In this fast PWM mode, the duty cycle is (OCR1A+1)/(ICR1+1). If you want a duty cycle of zero, you have to disengage the PWM and turn the pin to OUTPUT LOW. This is what the Arduino's analogWrite() does: it treats the value 0 as a special case. Note that 255 is also treated as a special case, although that is not useful. ...


Only top voted, non community-wiki answers of a minimum length are eligible