﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>Microcontrollers Discussions</title>
    <description>Latest discussions happening in the Microcontrollers category</description>
    <link>https://www.aboveunity.com</link>
    <item>
      <title>Pro Micro Microcontroller PWM</title>
      <description>&lt;p&gt;My Friends,&lt;/p&gt;&#xD;
&lt;p&gt;Many years now I have been super interested in PWM. Years ago I wrote a PWM project for Arduino, it was terrible, but it was a good start. Since then, I have written many more...&lt;/p&gt;&#xD;
&lt;p&gt;Today I want to share something of a bit more value than my first project, A PWM Project that has a lot more value:&lt;/p&gt;&#xD;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;h3&gt;The Code:&lt;/h3&gt;&#xD;
&lt;pre class="language-cpp"&gt;&lt;code&gt;////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// PWM Software written by Chris Sykes.                                                           //&#xD;
// NOTE: 16 bit Timers currently used. 32 Bit Timers need all shorts changed to longs!            //&#xD;
// Software written and shared as is, no warrantys are given. Use at your own risk.               //&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// Your MCU Clock Frequency: 16000000 or 16e6, retrieved by F_CPU.                                //&#xD;
long fclock = F_CPU;&#xD;
&#xD;
&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// Most MCU's have:                                                                               //&#xD;
//   0,                                                                                           //&#xD;
//   8,                                                                                           //&#xD;
//   64,                                                                                          //&#xD;
//   256,                                                                                         //&#xD;
//   1024                                                                                         //&#xD;
// as Prescaler Values:                                                                           //&#xD;
short Prescaler = 1024;&#xD;
&#xD;
&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// The MCU Setup Method:                                                                          //&#xD;
void setup() {//////////////////////////////////////////////////////////////////////////////////////&#xD;
&#xD;
  // Init Serial:&#xD;
  Serial.begin(115200);&#xD;
&#xD;
  // Confgure Timer:&#xD;
  ConfgureTimer(1.275, 21.525);&#xD;
}&#xD;
&#xD;
&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// Configure Timer:                                                                               //&#xD;
void ConfgureTimer(double frequency, double dutycycle){/////////////////////////////////////////////&#xD;
&#xD;
  // The counter simply overruns when it passes its maximum 16-bit value&#xD;
  // (MAX = 0xFFFF (65535)) and then restarts from the BOTTOM (0x0000).&#xD;
  &#xD;
  // Timer One PWM Pin:&#xD;
  // Check your Datasheet!&#xD;
  pinMode(10, OUTPUT);&#xD;
  &#xD;
  // Reset Timer One:&#xD;
  TCCR1A = 0;&#xD;
  TCCR1B = 0;&#xD;
&#xD;
  // ComA and B need to be set for Compare Match Pins:&#xD;
  TCCR1A |= (1 &amp;lt;&amp;lt; COM1A1) | (1 &amp;lt;&amp;lt; COM1B1);&#xD;
&#xD;
  // Configure Prescaler (CSX):&#xD;
  SetPrescaler(Prescaler);&#xD;
&#xD;
  // Set PWM Mode:&#xD;
  SetPWMMode();&#xD;
&#xD;
  // Set Frequency:&#xD;
  OCR1A = CalculateFrequency(frequency);&#xD;
&#xD;
  // Set Duty Cycle:&#xD;
  OCR1B = CalculateDutyCycle(OCR1A, dutycycle);&#xD;
}&#xD;
&#xD;
&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// Set Prescaler:                                                                                 //&#xD;
void SetPrescaler(short prescaler){/////////////////////////////////////////////////////////////////&#xD;
&#xD;
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
  // See your Datasheet! See: Clock Select Bit Description                                                 //&#xD;
  //-------------------------------------------------------------------------------------------------------//&#xD;
  // CS02     CS01     CS00     Description                                                                //&#xD;
  //  0        0        0        No clock source (Timer/Counter stopped)                                   //&#xD;
  //  0        0        1        clkI/O/(No prescaling)                                                    //&#xD;
  //  0        1        0        clkI/O/8 (From prescaler)                                                 //&#xD;
  //  0        1        1        clkI/O/64 (From prescaler)                                                //&#xD;
  //  1        0        0        clkI/O/256 (From prescaler)                                               //&#xD;
  //  1        0        1        clkI/O/1024 (From prescaler)                                              //&#xD;
  //  1        1        0        External clock source on T0 pin. Clock on falling edge.                   //&#xD;
  //  1        1        1        External clock source on T0 pin. Clock on rising edge.                    //&#xD;
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
&#xD;
  // Configure Prescaler (CSX):&#xD;
  switch (prescaler) {&#xD;
    case 0:&#xD;
      //  Set 0: clkI/O/(No prescaling)&#xD;
      TCCR1B |= (0 &amp;lt;&amp;lt; CS12) | (0 &amp;lt;&amp;lt; CS11) | (1 &amp;lt;&amp;lt; CS10);&#xD;
      break;&#xD;
    case 8:&#xD;
      // Set 8: clkI/O/8 (From prescaler)&#xD;
      TCCR1B |= (0 &amp;lt;&amp;lt; CS12) | (1 &amp;lt;&amp;lt; CS11) | (0 &amp;lt;&amp;lt; CS10);&#xD;
      break;&#xD;
    case 64:&#xD;
      // Set 64: clkI/O/64 (From prescaler)&#xD;
      TCCR1B |= (0 &amp;lt;&amp;lt; CS12) | (1 &amp;lt;&amp;lt; CS11) | (1 &amp;lt;&amp;lt; CS10);&#xD;
      break;&#xD;
    case 256:&#xD;
      // Set 256: clkI/O/256 (From prescaler)&#xD;
      TCCR1B |= (1 &amp;lt;&amp;lt; CS12) | (0 &amp;lt;&amp;lt; CS11) | (0 &amp;lt;&amp;lt; CS10);&#xD;
      break;&#xD;
    case 1024:&#xD;
      // Set 1024: clkI/O/1024 (From prescaler)&#xD;
      TCCR1B |= (1 &amp;lt;&amp;lt; CS12) | (0 &amp;lt;&amp;lt; CS11) | (1 &amp;lt;&amp;lt; CS10);&#xD;
      break;&#xD;
    default:&#xD;
      // Set Off: No clock source (Timer/Counter stopped)&#xD;
      TCCR1B |= (0 &amp;lt;&amp;lt; CS12) | (0 &amp;lt;&amp;lt; CS11) | (0 &amp;lt;&amp;lt; CS10);&#xD;
      break;&#xD;
  }&#xD;
}&#xD;
&#xD;
&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// Set PWM Mode:                                                                                  //&#xD;
void SetPWMMode(){//////////////////////////////////////////////////////////////////////////////////&#xD;
&#xD;
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
  // See your Datasheet!                                                                                            //&#xD;
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
  // Waveform Generation Mode Bit Description                                                                       //&#xD;
  //----------------------------------------------------------------------------------------------------------------//&#xD;
  //                                     Timer/Counter Mode of                    Update of       TOV Flag (1)(2)   //&#xD;
  // Mode    WGM3   WGM2   WGM1   WGM0   Operation                     TOP        OCRx at         Set on            //&#xD;
  //  0      0      0      0      0      Normal                        0xFFFF     Immediate       MAX               //&#xD;
  //  1      0      0      0      1      PWM, Phase Correct, 8-bit     0x00FF     TOP             BOTTOM            //&#xD;
  //  2      0      0      1      0      PWM, Phase Correct, 9-bit     0x01FF     TOP             BOTTOM            //&#xD;
  //  3      0      0      1      1      PWM, Phase Correct, 10-bit    0x03FF     TOP             BOTTOM            //&#xD;
  //  4      0      1      0      0      CTC                           OCRnA      Immediate       MAX               //&#xD;
  //  5      0      1      0      1      Fast PWM, 8-bit               0x00FF     TOP             TOP               //&#xD;
  //  6      0      1      1      0      Fast PWM, 9-bit               0x01FF     TOP             TOP               //&#xD;
  //  7      0      1      1      1      Fast PWM, 10-bit              0x03FF     TOP             TOP               //&#xD;
  //  8      1      0      0      0      PWM, PnFC                     ICRn       BOTTOM          BOTTOM            //&#xD;
  //  9      1      0      0      1      PWM, PnFC                     OCRnA      BOTTOM          BOTTOM            //&#xD;
  //  10     1      0      1      0      PWM, Phase Correct            ICRn       TOP             BOTTOM            //&#xD;
  //  11     1      0      1      1      PWM, Phase Correct            OCRnA      TOP             BOTTOM            //&#xD;
  //  12     1      1      0      0      CTC                           ICRn       Immediate       MAX               //&#xD;
  //  13     1      1      0      1      (Reserved)                    &amp;ndash;          &amp;ndash;               &amp;ndash;                 //&#xD;
  //  14     1      1      1      0      Fast PWM                      ICRn       TOP             TOP               //&#xD;
  //  15     1      1      1      1      Fast PWM                      OCRnA      TOP             TOP               //&#xD;
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
  // NOTE: PnFC = Phase and Frequency Correct.&#xD;
&#xD;
  // Fast PWM needs bits (WGM10 &amp;amp; WGM12) set to One:&#xD;
  TCCR1A |= (1 &amp;lt;&amp;lt; WGM10) | (1 &amp;lt;&amp;lt; WGM11);&#xD;
&#xD;
  // Configure Fast PWM Mode (WGM12 and 13):&#xD;
  TCCR1B |= (1 &amp;lt;&amp;lt; WGM12) | (1 &amp;lt;&amp;lt; WGM13);&#xD;
}&#xD;
&#xD;
&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// The MCU Loop Method:                                                                           //&#xD;
void loop() {///////////////////////////////////////////////////////////////////////////////////////&#xD;
&#xD;
  // Print Output:&#xD;
  PrintOutput();&#xD;
&#xD;
  // Delay:&#xD;
  delay(3000);&#xD;
}&#xD;
&#xD;
&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// Calculate the Frequency:                                                                       //&#xD;
short CalculateFrequency(double frequency){/////////////////////////////////////////////////////////&#xD;
&#xD;
  // Calculate OCR1A from specified Frequency:&#xD;
  return (short)(fclock / (frequency * Prescaler)) - 1L;&#xD;
}&#xD;
&#xD;
&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// Calculate the DutyCycle:                                                                       //&#xD;
short CalculateDutyCycle(int period, double duty){//////////////////////////////////////////////////&#xD;
&#xD;
  // Calculate OCR1B from OCR1A and specified Duty Cycle:&#xD;
  return (short)(period * (duty / 100L));&#xD;
}&#xD;
&#xD;
&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// Calculate Register Resolution:                                                                 //&#xD;
double CalculateResolution(short ocrx){////////////////////////////////////////////////////////////&#xD;
&#xD;
  return (log((double)ocrx + 1.0D)/log(2.0D));&#xD;
}&#xD;
&#xD;
&#xD;
////////////////////////////////////////////////////////////////////////////////////////////////////&#xD;
// Print Output Data:                                                                             //&#xD;
void PrintOutput(){/////////////////////////////////////////////////////////////////////////////////&#xD;
&#xD;
  // Shorts, Longs and other variable's dont mix well, convert to Double:&#xD;
  double Frequency = ((double)fclock / (((double)OCR1A + 1.0) * (double)Prescaler));&#xD;
  short Period = (short)((double)fclock / (Frequency * (double)Prescaler)) - 1.0;&#xD;
  &#xD;
  // Display Output:&#xD;
  Serial.print("Frequency: ");&#xD;
  Serial.print(Frequency);&#xD;
  Serial.print("Hz. Resolution: ");&#xD;
  Serial.print(CalculateResolution(OCR1A));&#xD;
  Serial.print(" bits. Period: ");&#xD;
  Serial.print(Period);&#xD;
  Serial.print("==");&#xD;
  Serial.print(OCR1A);&#xD;
  Serial.println(" comboblets");  &#xD;
}&lt;/code&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;Of course this is just the start, to get you started! You can use many Arduino Microcontrollers with this, from the &lt;a href="https://www.banggood.com/Geekcreit-Mega-WiFi-R3-Module-ATmega2560ESP8266-32Mb-Memory-USB-TTL-CH340G-p-1205437.html?rmmds=search&amp;amp;cur_warehouse=CN"&gt;Arduino Mega&lt;/a&gt;, Pin 12, to the &lt;a href="https://www.banggood.com/Pro-Micro-5V-16M-Mini-Leonardo-Microcontroller-Development-Board-p-1077675.html?rmmds=search&amp;amp;cur_warehouse=CN"&gt;Arduino Pro Micro&lt;/a&gt;, Pin 10, currently testing the Code on the Pro Micro:&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="../../../content/uploads/b5d8d256-5657-4ec2-ac7c-a741014a20b4/71d42c5f-78bf-4385-86f4-abe8004afc01_pro-micro.jpg?width=690&amp;amp;upscale=false" alt=""&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="../../../content/uploads/b5d8d256-5657-4ec2-ac7c-a741014a20b4/6ffbd717-3d1c-4b23-b7fb-abe8004b062f_pro-micro-pin-outs.jpg?width=690&amp;amp;upscale=false" alt=""&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;https://www.youtube.com/watch?v=DHxH1v_La5s&lt;/p&gt;&#xD;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;Of course, the Mega has different Pin Outs. This Code is very adaptable! Please post here if you need help changing the Code to suit your Microcontroller.&lt;/p&gt;&#xD;
&lt;p&gt;PWM can be used to drive any Mosfet, Transistor, SCR, Triac, Relay and many more Switching Options! For about $6.00 one of these can be purchased: &lt;a href="https://www.banggood.com/MOSFET-High-Power-Heated-Bed-Expansion-Power-Module-MOS-Tube-for-3D-Printer-Prusa-i3-Anet-A8A6-p-1356434.html?akmClientCountry=AU&amp;amp;rmmds=cart_middle_products&amp;amp;cur_warehouse=CN"&gt;MOSFET High Power&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="../../../content/uploads/b5d8d256-5657-4ec2-ac7c-a741014a20b4/53d4aa10-bee2-497d-b041-abe8004cb28f_mosfet-high-power-heated-bed-expansion-power-module.jpg?width=690&amp;amp;upscale=false" alt=""&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="../../../content/uploads/b5d8d256-5657-4ec2-ac7c-a741014a20b4/a0aea683-0d43-4cff-9dae-abe8004cbbfb_mosfet-high-power-heated-bed-expansion-power-module-img-01.jpg?width=690&amp;amp;upscale=false" alt=""&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;Of course, some sort of interface to update your Microsontroller can be used, USB Serial, WiFi or anything like this can be used to change the Frequency and Duty Cycle, but more Code will be required.&lt;/p&gt;&#xD;
&lt;p&gt;For less than $10.00 this is a great option to get started!&lt;/p&gt;&#xD;
&lt;p&gt;@Zanzal and other Dev's, please feel free to add Code or suggestions to improve the Code.&lt;/p&gt;&#xD;
&lt;p&gt;Best wishes, stay safe and well My Friends,&lt;/p&gt;&#xD;
&lt;p&gt;&amp;nbsp; &amp;nbsp;Chris&lt;/p&gt;</description>
      <pubDate>2020-06-28T04:40:20.7830000</pubDate>
      <link>https://www.aboveunity.com/thread/microcontroller-pwm-cheap-and-easy-start-to-getting-something-working/</link>
    </item>
  </channel>
</rss>