Hot answers tagged

31

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 ...


23

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 ...


15

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

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 ...


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 ...


11

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 ...


9

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; ...


9

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 ...


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 ...


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

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.


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

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

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 ...


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

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 ...


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

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 ...


5

From your code you are using Timer0 in FastPWM mode with top = 0xFF. In this mode, as used in your code, OCR0A defines the pulse width rate (more precisely, OCR0A / 256). Timer0 uses port OC0A and OC0B to ouput PWM signals, in your code, you are using only OC0A (which is perfectly fine). Now if you take a look at ATmega 328 data sheet, chapter 14.3.3 you ...


5

Just to add to @Ignacio's answer which has directly answered your question. The "conflict" you speak of is in relation to Timer0's prescaler. For the most part, you can use those pins (incidentally pins 5 and 6 on the UNO) with PWM without an issue, and read the correct value of millis() (as well as get the expected delay from delay) Where you run into ...


5

It is possible, but not the best idea. The analog inputs require a reasonably stable input - this can be achieved with a RC filter to smooth the PWM output. This would work for reasonably slow data rates. You would be better to use one of the many communication protocols supported by Arduino (serial, SPI, I²C).


5

Fixing the timekeeping functions with your PWM settings is not so simple. You should at least try to rewrite ISR(TIMER0_OVF_vect), micros(), and probably delay(). Here is why: First, there is a rounding problem. Time is kept using two global variables: volatile unsigned long timer0_millis; static unsigned char timer0_fract; The first one is what millis() ...


5

The analogWrite() function takes a value that is between 0 (fully off) and 255 (fully on). Your value of 150 to 240 is a value within that range of 0 to 255 and represents a percentage of the "on time" of the PWM signal. (150 / 255) * 100 = 58.8% on time (240 / 255) * 100 = 94.1% on time. You seem to have an "input value" of between 0 and 9 inclusive. ...


5

Your code assumes that TCCR0n are zero. But what if they are not. What if there is some hidden initialization? Timer0 is used by the Arduino micro/millis counter and the prescale (TCCR0B) is initiated by setting bits CS00 and CS01 in init() before setup() is called. If you really want to use Timer0 you will need to set/clear all the prescale bits. ...


5

I did not quite understand what you are actually trying to accomplish. Neither you question nor your code is very clear in this respect. And your code is probably buggy anyway, since it does not do what you expect. Then, I am just guessing: you may just want to fade a red LED up and down, then a green LED up and down, and repeat the whole cycle indefinitely....


5

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...


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