<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"  xmlns:isc="http://dtd.interspire.com/rss/isc-1.0.dtd">
	<channel>
		<title><![CDATA[Solutions Cubed, LLC: Latest News]]></title>
		<link>https://www.solutions-cubed.com</link>
		<description><![CDATA[The latest news from Solutions Cubed, LLC.]]></description>
		<pubDate>Sat, 30 May 2026 09:00:01 +0000</pubDate>
		<isc:store_title><![CDATA[Solutions Cubed, LLC]]></isc:store_title>
		<item>
			<title><![CDATA[Sensing Color With The Arduino and the TCS34725]]></title>
			<link>https://www.solutions-cubed.com/electronic-design-blog/sensing-color-with-the-arduino-and-the-tcs34725/</link>
			<pubDate>Tue, 14 Aug 2018 14:31:42 +0000</pubDate>
			<guid isPermaLink="false">https://www.solutions-cubed.com/electronic-design-blog/sensing-color-with-the-arduino-and-the-tcs34725/</guid>
			<description><![CDATA[<p><img src="/product_images/uploaded_images/tcs34725-1.png"><br></p><p>Sensing color with the Arduino and the TCS34725 is a pretty straight forward 
exercise.  The <a href="http://www.ams.com/eng/Products/Light-Sensors/Color-Sensor/TCS34725" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">TCS34725 
is an IC manufactured by AMS</a> (previously Taos).  It packages color sensing 
analog-to-digital converters for clear, red, green, and blue color sensing into 
a tiny 6 pin package.  The TCS34725 implements an I2C interface to configure 
settings and reading the color values.</p><p>In the photo above you can see a prototype of our BM017 color sensor module.  
We’ve included a white LED on the module that allows you to illuminate the 
object whose color you are sensing.</p><p><a href="http://blog.solutions-cubed.com/wp-content/uploads/2013/05/tcs34725_2.jpg"></a></p><p>Here’s an image of the senor measuring a blue sheet of paper.<br></p><p><img src="/product_images/uploaded_images/tcs34725-2.png"><br><br>Our first application with this sensor simply configures the TCS34725 and 
reads each color value one time per second.  Following that there’s a simple 
comparison of the red, green, and blue values to see which value is larger.  The 
largest value is assumed to be the color present.  Here are some points of 
interest from the work I did that might help you during implementation.</p><p>1.  Red is the color most easily measured.  Green and blue are closer in 
value and can be indistinguishable if the color sample is too far from the 
sensor.<br>2.  Since the sensor may be close to the object it is sampling we 
added a white LED to our module to allow illumination of the sample.<br>3.  The 
TCS34725 operates at 2.7V-3.6V.  The Arduino at 5V.  So our module also has a 
voltage level converter on the I2C pins allowing both devices to see the voltage 
they operate at.<br>4.  The Arduino code uses the wire library with the SDA and 
SCL pins associated with A4 and A5 respectively.<br>5.  The ATime setting in the 
TCS34725 determines the resolution of the color measurement.  I have mine set 
for 16-bit values, and I think the integration (measurement) time is about 
600mS.</p><p>This module will be available for resale in about 6 weeks.  I’ll place the 
schematic on our web site at some point in the next few weeks.  In the mean time 
here’s a screen capture.<br><br><br><a href="http://blog.solutions-cubed.com/wp-content/uploads/2013/05/bm017_schematic.png"></a></p><p><img src="/product_images/uploaded_images/bm017-schematic.png">The Arduino code will set the TCS34725 up for operation and check that it is 
connected to the I2C lines on power up.  Then it will read the color registers 
and try to determine which color is dominant.  If you enable the Serial Monitor 
it will display the color it sees as red, green, or blue.  If you want to see 
the raw measurements you can comment in that portion of the code and it will 
send the data to the Serial Monitor.<br></p><p><img src="/product_images/uploaded_images/bm017-arduino-screen-capture.png"></p><p><a href="http://blog.solutions-cubed.com/wp-content/uploads/2013/05/BM017-arduino-screen-capture.jpg"></a></p><p>Here is the code I used for simple color comparisons.</p><pre>/*
BM017_Arduino_color_sensing:  This program interfaces to the AMS TCS34725 color light
to digital converter IC.  It uses the Arduino I2C interface.  

Schematics associated with the BM017 module may be used for hardware wiring information.
See the user datasheet at &lt;a href="http://www.solutions-cubed.com"&gt;www.solutions-cubed.com&lt;/a&gt; for additional information.

*/

#include &lt;Wire.h&gt;
#include &lt;Math.h&gt;

byte i2cWriteBuffer[10&91;;
byte i2cReadBuffer[10&91;;

#define SensorAddressWrite 0x29 //
#define SensorAddressRead 0x29 // 
#define EnableAddress 0xa0 // register address + command bits
#define ATimeAddress 0xa1 // register address + command bits
#define WTimeAddress 0xa3 // register address + command bits
#define ConfigAddress 0xad // register address + command bits
#define ControlAddress 0xaf // register address + command bits
#define IDAddress 0xb2 // register address + command bits
#define ColorAddress 0xb4 // register address + command bits

/*  
Send register address and the byte value you want to write the magnetometer and 
loads the destination register with the value you send
*/
void Writei2cRegisters(byte numberbytes, byte command)
{
    byte i = 0;

    Wire.beginTransmission(SensorAddressWrite);   // Send address with Write bit set
    Wire.write(command);                          // Send command, normally the register address 
    for (i=0;i&lt;numberbytes;i++)                       // Send data 
      Wire.write(i2cWriteBuffer[i&91;);
    Wire.endTransmission();

    delayMicroseconds(100);      // allow some time for bus to settle      
}

/*  
Send register address to this function and it returns byte value
for the magnetometer register's contents 
*/
byte Readi2cRegisters(int numberbytes, byte command)
{
   byte i = 0;

    Wire.beginTransmission(SensorAddressWrite);   // Write address of read to sensor
    Wire.write(command);
    Wire.endTransmission();

    delayMicroseconds(100);      // allow some time for bus to settle      

    Wire.requestFrom(SensorAddressRead,numberbytes);   // read data
    for(i=0;i&lt;numberbytes;i++)
      i2cReadBuffer[i&91; = Wire.read();
    Wire.endTransmission();   

    delayMicroseconds(100);      // allow some time for bus to settle      
}  

void init_TCS34725(void)
{
  i2cWriteBuffer[0&91; = 0x10;
  Writei2cRegisters(1,ATimeAddress);    // RGBC timing is 256 - contents x 2.4mS =  
  i2cWriteBuffer[0&91; = 0x00;
  Writei2cRegisters(1,ConfigAddress);   // Can be used to change the wait time
  i2cWriteBuffer[0&91; = 0x00;
  Writei2cRegisters(1,ControlAddress);  // RGBC gain control
  i2cWriteBuffer[0&91; = 0x03;
  Writei2cRegisters(1,EnableAddress);    // enable ADs and oscillator for sensor  
}

void get_TCS34725ID(void)
{
  Readi2cRegisters(1,IDAddress);
  if (i2cReadBuffer[0&91; = 0x44)
    Serial.println("TCS34725 is present");    
  else
    Serial.println("TCS34725 not responding");    
}

/*
Reads the register values for clear, red, green, and blue.
*/
void get_Colors(void)
{
  unsigned int clear_color = 0;
  unsigned int red_color = 0;
  unsigned int green_color = 0;
  unsigned int blue_color = 0;

  Readi2cRegisters(8,ColorAddress);
  clear_color = (unsigned int)(i2cReadBuffer[1&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[0&91;;
  red_color = (unsigned int)(i2cReadBuffer[3&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[2&91;;
  green_color = (unsigned int)(i2cReadBuffer[5&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[4&91;;
  blue_color = (unsigned int)(i2cReadBuffer[7&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[6&91;;

  // send register values to the serial monitor 
/*
  Serial.print("clear color=");
  Serial.print(clear_color, DEC);    
  Serial.print(" red color=");
  Serial.print(red_color, DEC);    
  Serial.print(" green color=");
  Serial.print(green_color, DEC);    
  Serial.print(" blue color=");
  Serial.println(blue_color, DEC);
*/

 // Basic RGB color differentiation can be accomplished by comparing the values and the largest reading will be 
 // the prominent color

  if((red_color&gt;blue_color) &amp;&amp; (red_color&gt;green_color))
    Serial.println("detecting red");
  else if((green_color&gt;blue_color) &amp;&amp; (green_color&gt;red_color))
    Serial.println("detecting green");
  else if((blue_color&gt;red_color) &amp;&amp; (blue_color&gt;green_color))
    Serial.println("detecting blue");
  else
    Serial.println("color not detectable");

}  

void setup() {
  Wire.begin();
  Serial.begin(9600);  // start serial for output
  init_TCS34725();
  get_TCS34725ID();     // get the device ID, this is just a test to see if we're connected
}

void loop() {
    get_Colors();
    delay(1000);
}</pre>]]></description>
			<content:encoded><![CDATA[<p><img src="/product_images/uploaded_images/tcs34725-1.png"><br></p><p>Sensing color with the Arduino and the TCS34725 is a pretty straight forward 
exercise.  The <a href="http://www.ams.com/eng/Products/Light-Sensors/Color-Sensor/TCS34725" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">TCS34725 
is an IC manufactured by AMS</a> (previously Taos).  It packages color sensing 
analog-to-digital converters for clear, red, green, and blue color sensing into 
a tiny 6 pin package.  The TCS34725 implements an I2C interface to configure 
settings and reading the color values.</p><p>In the photo above you can see a prototype of our BM017 color sensor module.  
We’ve included a white LED on the module that allows you to illuminate the 
object whose color you are sensing.</p><p><a href="http://blog.solutions-cubed.com/wp-content/uploads/2013/05/tcs34725_2.jpg"></a></p><p>Here’s an image of the senor measuring a blue sheet of paper.<br></p><p><img src="/product_images/uploaded_images/tcs34725-2.png"><br><br>Our first application with this sensor simply configures the TCS34725 and 
reads each color value one time per second.  Following that there’s a simple 
comparison of the red, green, and blue values to see which value is larger.  The 
largest value is assumed to be the color present.  Here are some points of 
interest from the work I did that might help you during implementation.</p><p>1.  Red is the color most easily measured.  Green and blue are closer in 
value and can be indistinguishable if the color sample is too far from the 
sensor.<br>2.  Since the sensor may be close to the object it is sampling we 
added a white LED to our module to allow illumination of the sample.<br>3.  The 
TCS34725 operates at 2.7V-3.6V.  The Arduino at 5V.  So our module also has a 
voltage level converter on the I2C pins allowing both devices to see the voltage 
they operate at.<br>4.  The Arduino code uses the wire library with the SDA and 
SCL pins associated with A4 and A5 respectively.<br>5.  The ATime setting in the 
TCS34725 determines the resolution of the color measurement.  I have mine set 
for 16-bit values, and I think the integration (measurement) time is about 
600mS.</p><p>This module will be available for resale in about 6 weeks.  I’ll place the 
schematic on our web site at some point in the next few weeks.  In the mean time 
here’s a screen capture.<br><br><br><a href="http://blog.solutions-cubed.com/wp-content/uploads/2013/05/bm017_schematic.png"></a></p><p><img src="/product_images/uploaded_images/bm017-schematic.png">The Arduino code will set the TCS34725 up for operation and check that it is 
connected to the I2C lines on power up.  Then it will read the color registers 
and try to determine which color is dominant.  If you enable the Serial Monitor 
it will display the color it sees as red, green, or blue.  If you want to see 
the raw measurements you can comment in that portion of the code and it will 
send the data to the Serial Monitor.<br></p><p><img src="/product_images/uploaded_images/bm017-arduino-screen-capture.png"></p><p><a href="http://blog.solutions-cubed.com/wp-content/uploads/2013/05/BM017-arduino-screen-capture.jpg"></a></p><p>Here is the code I used for simple color comparisons.</p><pre>/*
BM017_Arduino_color_sensing:  This program interfaces to the AMS TCS34725 color light
to digital converter IC.  It uses the Arduino I2C interface.  

Schematics associated with the BM017 module may be used for hardware wiring information.
See the user datasheet at &lt;a href="http://www.solutions-cubed.com"&gt;www.solutions-cubed.com&lt;/a&gt; for additional information.

*/

#include &lt;Wire.h&gt;
#include &lt;Math.h&gt;

byte i2cWriteBuffer[10&91;;
byte i2cReadBuffer[10&91;;

#define SensorAddressWrite 0x29 //
#define SensorAddressRead 0x29 // 
#define EnableAddress 0xa0 // register address + command bits
#define ATimeAddress 0xa1 // register address + command bits
#define WTimeAddress 0xa3 // register address + command bits
#define ConfigAddress 0xad // register address + command bits
#define ControlAddress 0xaf // register address + command bits
#define IDAddress 0xb2 // register address + command bits
#define ColorAddress 0xb4 // register address + command bits

/*  
Send register address and the byte value you want to write the magnetometer and 
loads the destination register with the value you send
*/
void Writei2cRegisters(byte numberbytes, byte command)
{
    byte i = 0;

    Wire.beginTransmission(SensorAddressWrite);   // Send address with Write bit set
    Wire.write(command);                          // Send command, normally the register address 
    for (i=0;i&lt;numberbytes;i++)                       // Send data 
      Wire.write(i2cWriteBuffer[i&91;);
    Wire.endTransmission();

    delayMicroseconds(100);      // allow some time for bus to settle      
}

/*  
Send register address to this function and it returns byte value
for the magnetometer register's contents 
*/
byte Readi2cRegisters(int numberbytes, byte command)
{
   byte i = 0;

    Wire.beginTransmission(SensorAddressWrite);   // Write address of read to sensor
    Wire.write(command);
    Wire.endTransmission();

    delayMicroseconds(100);      // allow some time for bus to settle      

    Wire.requestFrom(SensorAddressRead,numberbytes);   // read data
    for(i=0;i&lt;numberbytes;i++)
      i2cReadBuffer[i&91; = Wire.read();
    Wire.endTransmission();   

    delayMicroseconds(100);      // allow some time for bus to settle      
}  

void init_TCS34725(void)
{
  i2cWriteBuffer[0&91; = 0x10;
  Writei2cRegisters(1,ATimeAddress);    // RGBC timing is 256 - contents x 2.4mS =  
  i2cWriteBuffer[0&91; = 0x00;
  Writei2cRegisters(1,ConfigAddress);   // Can be used to change the wait time
  i2cWriteBuffer[0&91; = 0x00;
  Writei2cRegisters(1,ControlAddress);  // RGBC gain control
  i2cWriteBuffer[0&91; = 0x03;
  Writei2cRegisters(1,EnableAddress);    // enable ADs and oscillator for sensor  
}

void get_TCS34725ID(void)
{
  Readi2cRegisters(1,IDAddress);
  if (i2cReadBuffer[0&91; = 0x44)
    Serial.println("TCS34725 is present");    
  else
    Serial.println("TCS34725 not responding");    
}

/*
Reads the register values for clear, red, green, and blue.
*/
void get_Colors(void)
{
  unsigned int clear_color = 0;
  unsigned int red_color = 0;
  unsigned int green_color = 0;
  unsigned int blue_color = 0;

  Readi2cRegisters(8,ColorAddress);
  clear_color = (unsigned int)(i2cReadBuffer[1&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[0&91;;
  red_color = (unsigned int)(i2cReadBuffer[3&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[2&91;;
  green_color = (unsigned int)(i2cReadBuffer[5&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[4&91;;
  blue_color = (unsigned int)(i2cReadBuffer[7&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[6&91;;

  // send register values to the serial monitor 
/*
  Serial.print("clear color=");
  Serial.print(clear_color, DEC);    
  Serial.print(" red color=");
  Serial.print(red_color, DEC);    
  Serial.print(" green color=");
  Serial.print(green_color, DEC);    
  Serial.print(" blue color=");
  Serial.println(blue_color, DEC);
*/

 // Basic RGB color differentiation can be accomplished by comparing the values and the largest reading will be 
 // the prominent color

  if((red_color&gt;blue_color) &amp;&amp; (red_color&gt;green_color))
    Serial.println("detecting red");
  else if((green_color&gt;blue_color) &amp;&amp; (green_color&gt;red_color))
    Serial.println("detecting green");
  else if((blue_color&gt;red_color) &amp;&amp; (blue_color&gt;green_color))
    Serial.println("detecting blue");
  else
    Serial.println("color not detectable");

}  

void setup() {
  Wire.begin();
  Serial.begin(9600);  // start serial for output
  init_TCS34725();
  get_TCS34725ID();     // get the device ID, this is just a test to see if we're connected
}

void loop() {
    get_Colors();
    delay(1000);
}</pre>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Color Sensor to RGB LED Driver with an Arduino]]></title>
			<link>https://www.solutions-cubed.com/electronic-design-blog/color-sensor-to-rgb-led-driver-with-an-arduino/</link>
			<pubDate>Tue, 14 Aug 2018 14:31:34 +0000</pubDate>
			<guid isPermaLink="false">https://www.solutions-cubed.com/electronic-design-blog/color-sensor-to-rgb-led-driver-with-an-arduino/</guid>
			<description><![CDATA[<p><img src="/product_images/uploaded_images/bm017-sensor.png"><br><br><span style="font-family: Arial;"><span style=""><span style="color: rgb(0, 0, 0);"><br></span></span></span></p><p><span style="font-family: Arial;"><span style=""><span style="color: rgb(0, 0, 0);">I’m in the process of adding the BM017 Color Sensor to our web site.  This 
breakout module is based on the <a href="http://www.ams.com/eng/Products/Light-Sensors/Color-Sensor/TCS34725" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">TCS34725</a> 
by AMS (formerly Taos).  You can use it to detect red, green, blue, and clear 
color values from object in front of the sensor. I covered basic use of the 
sensor in my post <a href="http://blog.solutions-cubed.com/sensing-color-with-the-arduino-and-the-tcs34725/" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">Sensing 
Color with the Arduino and the TCS34725</a>.  The code I use here builds on 
that blog post.</span></span></span></p><p>I was interested in writing some Arduino code that would use the BM017 to 
sense colors and then use the readings to drive an RGB LED.  The goal was to 
place a color in front of the sensor and have the RGB LED turn the same color.  
It turns out this is pretty easy to do, but there are a couple of “gotchas”.</p><p><img src="/product_images/uploaded_images/bm017-schematic.png">Since the BM017 provides red, green, and blue (RGB) color components of the 
object in its field of view it makes sense that you can use the ratio of the 
color sensor readings to drive an RGB LED to match the object’s color.  I took a 
colorimetry class in college (back when dinosaurs roamed the earth).  From what 
I recall color measurements are complicated things.  I was hoping to avoid 
things like considerations of color temperature, luminescence, and any need for 
special chromatic instrumentation.  After all, this was supposed to be a couple 
of hours of messing around in the lab.</p><p>I used an Arduino Uno to get data from the color sensor, then generated 3 PWM 
signals in the Arduino to drive a high current RGB LED.  The schematic is 
above.  Here are a few things I figured out during the project.</p><p><strong>Output</strong>:  Not all RGB LEDs are the same, so you may have to 
adjust the program based on yours.  Each LED in the RGB package has a different 
forward voltage.  Each LED also has a different current rating for its highest 
brightness.  For example, in my RGB LED red peaked at 140mA, green at 160mA, and 
blue at 125mA.  I powered my RGB LED off of 5V and used different resistor 
values for each color component of the LED.  My goal was to have 100% duty 
cycle for each LED color be the highest brightness point for that color.  If 
each color component was equal I would have an output that was white.  This is 
is not what I saw in the lab with my initial hardware setup.  With all PWM 
outputs equal my white was more like a yellow.  I could modify resistor values.  
After some experimentation I determined there was too much green.  I used a 
scaling factor (variables “redintensity”, “greenintensity”, “blueintensity”) to 
reduce the amount of green as compared to red and blue.  This could also be done 
in hardware by increasing the resistor value on the green LED.</p><p>I also noted that at drive signals below ~50% the RGB LED I was using 
appeared to strobe.  This was interesting, because the PWM signal’s period was 
too fast to cause the strobe.  I think the blue and green LEDs were “dropping 
out” at lower duty cycles due to higher forward voltages.  I used the intensity 
variables to keep the PWM signals higher.</p><p>Lastly, a word of caution.  For my experiment I used a high brightness “true 
blue” RGB LED.  This LED can draw 400+ mA.  It is so bright  that it hurts your 
eyes to look at it.  Seriously, I left it uncovered and just a couple of glances 
at it had my eyes aching.  I had to cover it with a frosted glass candle 
holder.  This helped diffuse the color being generated as well as saving me from 
blindness.</p><p>The code below was what I used in the Arduino to convert color readings to 
PWM signals to drive the RGB LED.<br>Here are links for the source code 
discussed in this blog.<br><a href="https://store-qifphnsc.mybigcommerce.com/content/Downloads/Breakout%20Modules/BM017_Arduino_color_sensing.zip">BM017_Arduino_color_sensing.zip</a> 
-  Arduino Uno3 code example for basic red, green, and blue color sensing.<br><a href="https://store-qifphnsc.mybigcommerce.com/content/Downloads/Breakout%20Modules/BM017_Arduino_RGB_LED_driver.zip">BM017_Arduino_RGB_LED_driver.zip</a> 
-  Arduino Uno3 code example reading color and converting it to RGB LED drive 
signals.</p><pre>void drive_LEDs(void)
{
// intensity” floating point registers can be 
// used to adjust for LEDs of different intensity.  
// Equal r, g, and b values should output a 
// white light.

  redintensity = 2;   // 
  greenintensity = 1.8;  // 
  blueintensity = 2;  //

// Normalized value * intensity adjustment  
  rednorm = rednorm*redintensity;
  greennorm = greennorm*greenintensity;
  bluenorm = bluenorm*blueintensity;

// Convert value to PWM drive  
  rednorm = rednorm*255;
  greennorm = greennorm*255;
  bluenorm = bluenorm*255;

// Make sure to limit values to max PWM 
  if (rednorm &gt; 255)
    rednorm = 255;
  if (greennorm &gt; 255)
    greennorm = 255;
  if (bluenorm &gt; 255)
    bluenorm = 255;

// Output PWM values
 analogWrite(redPin,(int)(rednorm));
 analogWrite(greenPin,(int)(greennorm));
 analogWrite(bluePin,(int)(bluenorm));

  // send register values to the serial monitor 
  Serial.print("r=");
  Serial.print((int)(rednorm), DEC);    
  Serial.print(" g=");
  Serial.print((int)(greennorm), DEC);    
  Serial.print(" b=");
  Serial.println((int)(bluenorm), DEC);    

}</pre><p><strong>Input:</strong>  I’ve covered the I2C communication with the TCS34725 
in my previous blog (linked above).  That blog shows how to reads data from the 
sensor using I2C.  I still had to figure out what I was going to put in front of 
the color sensor, and I had a couple of options.  I first tried turning on the 
the white illumination LED on the BM017 and measuring colors off of colored 
cards I made from things around the office.  This kind of worked, but I didn’t 
have a wide range of colors I could test.</p><p><img src="/product_images/uploaded_images/bm017-iphone-app.png">Eventually I downloaded an RGB app for my iPhone.  This allowed me to 
experiment with a variety of colors and know what the R, G, and B ratios were 
for the colors I was testing.  There was an added benefit of the iPhone screen 
providing its own illumination for the sensor.</p><p>Initially I normalized the color values by creating a percentage of the color 
value relative to the maximum integration value possible.  For example, with my 
settings the highest color value could be 10240.  Unfortunately, even with the 
gain set high, I was only getting to about 30% of the peak value.  I then tried 
using the “clear” color value as my peak value, and this seemed to do the 
trick.  The clear color measurement gives a good indication of the maximum color 
value for the R, G, and B readings.</p><pre>/*
Reads the register values for clear, red, green, and blue.
*/
void get_Colors(void)
{
  unsigned int clear_color = 0;
  unsigned int red_color = 0;
  unsigned int green_color = 0;
  unsigned int blue_color = 0;

// read the color registers
  Readi2cRegisters(8,ColorAddress);
  clear_color = (unsigned int)(i2cReadBuffer[1&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[0&91;;
  red_color = (unsigned int)(i2cReadBuffer[3&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[2&91;;
  green_color = (unsigned int)(i2cReadBuffer[5&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[4&91;;
  blue_color = (unsigned int)(i2cReadBuffer[7&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[6&91;;

// normalize the colors 
  rednorm = (float)red_color/(float)clear_color;
  greennorm = (float)green_color/(float)clear_color;
  bluenorm = (float)blue_color/(float)clear_color;

}</pre><p>You can down load the entire Arduino code from our web site on the BM017 page 
or on our application notes page.</p><p>Here were some of the results from the various color matching attempts.</p><p><a href="http://blog.solutions-cubed.com/wp-content/uploads/2013/08/bm017_blue.jpg"></a></p><p><a href="http://blog.solutions-cubed.com/wp-content/uploads/2013/08/bm017_green.jpg"></a></p><p><img src="/product_images/uploaded_images/bm017-blue.png"></p><p><img src="/product_images/uploaded_images/bm017-green.png"></p><p><img src="/product_images/uploaded_images/bm017-orange.png"></p><p><img src="/product_images/uploaded_images/bm017-pink.png" style="width: 547px;"></p>]]></description>
			<content:encoded><![CDATA[<p><img src="/product_images/uploaded_images/bm017-sensor.png"><br><br><span style="font-family: Arial;"><span style=""><span style="color: rgb(0, 0, 0);"><br></span></span></span></p><p><span style="font-family: Arial;"><span style=""><span style="color: rgb(0, 0, 0);">I’m in the process of adding the BM017 Color Sensor to our web site.  This 
breakout module is based on the <a href="http://www.ams.com/eng/Products/Light-Sensors/Color-Sensor/TCS34725" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">TCS34725</a> 
by AMS (formerly Taos).  You can use it to detect red, green, blue, and clear 
color values from object in front of the sensor. I covered basic use of the 
sensor in my post <a href="http://blog.solutions-cubed.com/sensing-color-with-the-arduino-and-the-tcs34725/" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">Sensing 
Color with the Arduino and the TCS34725</a>.  The code I use here builds on 
that blog post.</span></span></span></p><p>I was interested in writing some Arduino code that would use the BM017 to 
sense colors and then use the readings to drive an RGB LED.  The goal was to 
place a color in front of the sensor and have the RGB LED turn the same color.  
It turns out this is pretty easy to do, but there are a couple of “gotchas”.</p><p><img src="/product_images/uploaded_images/bm017-schematic.png">Since the BM017 provides red, green, and blue (RGB) color components of the 
object in its field of view it makes sense that you can use the ratio of the 
color sensor readings to drive an RGB LED to match the object’s color.  I took a 
colorimetry class in college (back when dinosaurs roamed the earth).  From what 
I recall color measurements are complicated things.  I was hoping to avoid 
things like considerations of color temperature, luminescence, and any need for 
special chromatic instrumentation.  After all, this was supposed to be a couple 
of hours of messing around in the lab.</p><p>I used an Arduino Uno to get data from the color sensor, then generated 3 PWM 
signals in the Arduino to drive a high current RGB LED.  The schematic is 
above.  Here are a few things I figured out during the project.</p><p><strong>Output</strong>:  Not all RGB LEDs are the same, so you may have to 
adjust the program based on yours.  Each LED in the RGB package has a different 
forward voltage.  Each LED also has a different current rating for its highest 
brightness.  For example, in my RGB LED red peaked at 140mA, green at 160mA, and 
blue at 125mA.  I powered my RGB LED off of 5V and used different resistor 
values for each color component of the LED.  My goal was to have 100% duty 
cycle for each LED color be the highest brightness point for that color.  If 
each color component was equal I would have an output that was white.  This is 
is not what I saw in the lab with my initial hardware setup.  With all PWM 
outputs equal my white was more like a yellow.  I could modify resistor values.  
After some experimentation I determined there was too much green.  I used a 
scaling factor (variables “redintensity”, “greenintensity”, “blueintensity”) to 
reduce the amount of green as compared to red and blue.  This could also be done 
in hardware by increasing the resistor value on the green LED.</p><p>I also noted that at drive signals below ~50% the RGB LED I was using 
appeared to strobe.  This was interesting, because the PWM signal’s period was 
too fast to cause the strobe.  I think the blue and green LEDs were “dropping 
out” at lower duty cycles due to higher forward voltages.  I used the intensity 
variables to keep the PWM signals higher.</p><p>Lastly, a word of caution.  For my experiment I used a high brightness “true 
blue” RGB LED.  This LED can draw 400+ mA.  It is so bright  that it hurts your 
eyes to look at it.  Seriously, I left it uncovered and just a couple of glances 
at it had my eyes aching.  I had to cover it with a frosted glass candle 
holder.  This helped diffuse the color being generated as well as saving me from 
blindness.</p><p>The code below was what I used in the Arduino to convert color readings to 
PWM signals to drive the RGB LED.<br>Here are links for the source code 
discussed in this blog.<br><a href="https://store-qifphnsc.mybigcommerce.com/content/Downloads/Breakout%20Modules/BM017_Arduino_color_sensing.zip">BM017_Arduino_color_sensing.zip</a> 
-  Arduino Uno3 code example for basic red, green, and blue color sensing.<br><a href="https://store-qifphnsc.mybigcommerce.com/content/Downloads/Breakout%20Modules/BM017_Arduino_RGB_LED_driver.zip">BM017_Arduino_RGB_LED_driver.zip</a> 
-  Arduino Uno3 code example reading color and converting it to RGB LED drive 
signals.</p><pre>void drive_LEDs(void)
{
// intensity” floating point registers can be 
// used to adjust for LEDs of different intensity.  
// Equal r, g, and b values should output a 
// white light.

  redintensity = 2;   // 
  greenintensity = 1.8;  // 
  blueintensity = 2;  //

// Normalized value * intensity adjustment  
  rednorm = rednorm*redintensity;
  greennorm = greennorm*greenintensity;
  bluenorm = bluenorm*blueintensity;

// Convert value to PWM drive  
  rednorm = rednorm*255;
  greennorm = greennorm*255;
  bluenorm = bluenorm*255;

// Make sure to limit values to max PWM 
  if (rednorm &gt; 255)
    rednorm = 255;
  if (greennorm &gt; 255)
    greennorm = 255;
  if (bluenorm &gt; 255)
    bluenorm = 255;

// Output PWM values
 analogWrite(redPin,(int)(rednorm));
 analogWrite(greenPin,(int)(greennorm));
 analogWrite(bluePin,(int)(bluenorm));

  // send register values to the serial monitor 
  Serial.print("r=");
  Serial.print((int)(rednorm), DEC);    
  Serial.print(" g=");
  Serial.print((int)(greennorm), DEC);    
  Serial.print(" b=");
  Serial.println((int)(bluenorm), DEC);    

}</pre><p><strong>Input:</strong>  I’ve covered the I2C communication with the TCS34725 
in my previous blog (linked above).  That blog shows how to reads data from the 
sensor using I2C.  I still had to figure out what I was going to put in front of 
the color sensor, and I had a couple of options.  I first tried turning on the 
the white illumination LED on the BM017 and measuring colors off of colored 
cards I made from things around the office.  This kind of worked, but I didn’t 
have a wide range of colors I could test.</p><p><img src="/product_images/uploaded_images/bm017-iphone-app.png">Eventually I downloaded an RGB app for my iPhone.  This allowed me to 
experiment with a variety of colors and know what the R, G, and B ratios were 
for the colors I was testing.  There was an added benefit of the iPhone screen 
providing its own illumination for the sensor.</p><p>Initially I normalized the color values by creating a percentage of the color 
value relative to the maximum integration value possible.  For example, with my 
settings the highest color value could be 10240.  Unfortunately, even with the 
gain set high, I was only getting to about 30% of the peak value.  I then tried 
using the “clear” color value as my peak value, and this seemed to do the 
trick.  The clear color measurement gives a good indication of the maximum color 
value for the R, G, and B readings.</p><pre>/*
Reads the register values for clear, red, green, and blue.
*/
void get_Colors(void)
{
  unsigned int clear_color = 0;
  unsigned int red_color = 0;
  unsigned int green_color = 0;
  unsigned int blue_color = 0;

// read the color registers
  Readi2cRegisters(8,ColorAddress);
  clear_color = (unsigned int)(i2cReadBuffer[1&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[0&91;;
  red_color = (unsigned int)(i2cReadBuffer[3&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[2&91;;
  green_color = (unsigned int)(i2cReadBuffer[5&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[4&91;;
  blue_color = (unsigned int)(i2cReadBuffer[7&91;&lt;&lt;8) + (unsigned int)i2cReadBuffer[6&91;;

// normalize the colors 
  rednorm = (float)red_color/(float)clear_color;
  greennorm = (float)green_color/(float)clear_color;
  bluenorm = (float)blue_color/(float)clear_color;

}</pre><p>You can down load the entire Arduino code from our web site on the BM017 page 
or on our application notes page.</p><p>Here were some of the results from the various color matching attempts.</p><p><a href="http://blog.solutions-cubed.com/wp-content/uploads/2013/08/bm017_blue.jpg"></a></p><p><a href="http://blog.solutions-cubed.com/wp-content/uploads/2013/08/bm017_green.jpg"></a></p><p><img src="/product_images/uploaded_images/bm017-blue.png"></p><p><img src="/product_images/uploaded_images/bm017-green.png"></p><p><img src="/product_images/uploaded_images/bm017-orange.png"></p><p><img src="/product_images/uploaded_images/bm017-pink.png" style="width: 547px;"></p>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Debugging Arduino Sketches with Atmel Studio 7]]></title>
			<link>https://www.solutions-cubed.com/electronic-design-blog/debugging-arduino-sketches-with-atmel-studio-7/</link>
			<pubDate>Thu, 12 Jul 2018 12:29:55 +0000</pubDate>
			<guid isPermaLink="false">https://www.solutions-cubed.com/electronic-design-blog/debugging-arduino-sketches-with-atmel-studio-7/</guid>
			<description><![CDATA[<p>
	<img src="/product_images/uploaded_images/debug-breakpoint.jpg"></p><p>
	Atmel’s Studio 7 (Atmel is now owned by Microchip) allows you to import Arduino sketches and debug 
them.  This brings the Arduino into the realm of a professional design engineer 
tool.</p><p>
	Getting an Arduino to the point of debuggin’ its 
firmware is a pretty easy process, but does take several steps.  Here are some 
things you’ll want to take note of before beginning…</p><p>
	1.  You’ll need a debugger/programmer.  I used the <a href="http://www.atmel.com/tools/atatmel-ice.aspx">Atmel-ICE</a> which retails 
for about $60US and comes with a connector compatible with the Arduino ICSP 
connection.</p><p>
	2.  I used an Arduino Uno 3.  There could be some differences between this 
Arduino and other styles.</p><p>
	3.  You’ll have to download and install <a href="http://www.atmel.com/Microsite/atmel-studio/">AtmelStudio 7</a>.  This 
development environment is based on Microsoft’s Visual Studio.  I’m pretty 
familiar with Visual Studio, so getting up to speed with AtmelStudio was not a 
problem.  I won’t go into any detail here on how to use AtmelStudio beyond 
getting a project running and recovering the Arduino.</p><p>
	4.  Speaking of recovering the Arduino… you have to make a simple hardware 
change to allow ‘debugWire’ to work with the Arduino.  Additionally, programming 
the sketch using AtmelStudio will wipe out the Arduino bootloader, so you may 
want to recover it if you intend on using the Arduino for other projects.</p><p>
	5.  It’s a good idea to read through this blog before jumping into this.  If 
you’re not comfortable with the changes you’ll be making to the Arduino you 
should probably not try this.</p><p>
	Okay, here we go…</p><p>
	Hardware Mods:The Arduino Uno 3 microcontroller, an 
ATmega328p, comes loaded with a serial bootloader (optiboot_atmega328.hex).  The 
bootloader is a program that runs on reset and programs the microcontroller’s 
memory with values sent via a serial interface.  This program is what allows 
new sketches to be uploaded to the device.  The bootloader is entered when the 
serial DTR line briefly changes state.  In the schematic clip below the line 
marked CH1 is the DTR line, and CH2 is the RESET line.
	</p><p>
	<img src="/product_images/uploaded_images/arduino-programming.jpg"></p><p>
	Here is the reset pulse captured by an oscilloscope as a sketch is uploaded 
to the Arduino.
	</p><p>
	<img src="/product_images/uploaded_images/arduino-dtr.jpg"></p><p>
	Unfortunately, C5 in the schematic impacts Atmel’s ‘debugWIRE’ debugger 
interface, which also relies on control of the ATmega328p reset line.  
Fortunately, and helpfully, the Arduino people have left a jumper cut-line on 
the PCB that allows you to disconnect C5 from the reset line.
	</p><p>
	Using a razor blade or other sharp tool cut the trace that connects the two 
tinned pads labeled ‘RESET EN’.  Be sure not to cut the trace that runs from one 
of the pads to C5.  
	NOTE… 
without this trace the Arduino will no longer be programmable with the Arduino 
software even if the bootloader is present on the microcontroller.  FYI, C5 is 
the capacitor closest to the tinned pads, and is not marked on the PCB.
	</p><p>
	<img src="/product_images/uploaded_images/cut-reset.jpg"></p><p>
	<strong><a href="file:///C:/Users/Lon/AppData/Local/Temp/WindowsLiveWriter1286139640/supfiles8F34E18C/cut_reset4.jpg"></a></strong></p><p>Once this cut is made you can proceed to debugging an Arduino sketch.  
However, I added a 2-pin header across the tinned pads that allow me to switch 
between Atmel’s ‘debugWIRE’ interface and the standard Arduino serial bootload 
mode.  This is done by removing or adding a jumper.
	</p><p><img src="/product_images/uploaded_images/ard-jumper.jpg"></p><p>
	In order to import and debug an Arduino sketch you need to do the 
following…
	</p><p>
	1.  Make sure the reset is disconnected from C5, in my case this is done by 
removing the jumper from the 2-pin header I installed.
	</p><p>
	2. Plug the Atmel-ICE 6-pin header over the 3x2 footprint marked ICSP.  The 
tab on the Atmel-ICE receptacle should face inboard (toward C5) of the Arduino 
Uno 3.  If you’re not using the Arduino Uno 3 the tab of the Atmel-ICE connector 
is on the same side of the 3x2 header as pin 1.
	</p><p>
	3. You’ll need to power the Arduino Uno through the USB or power supply 
port.
	</p><p><img src="/product_images/uploaded_images/debugging.jpg"></p><p>
	Importing and Debugging the Sketch:</p><p>
	Now that the hardware is ready you can launch AtmelStudio and begin to import 
the Arduino sketch.  In my case I’m just going to import and debug the Blink 
sketch.
	</p><p>
	Launch AtmelStudio and select New Project from the Start menu.</p><p>
	Select “Create project from Arduino sketch”.  Enter a Name, Project Name, and 
browse to where you want to keep it, then click the OK button.
	</p><p><img src="/product_images/uploaded_images/new-project-screen.jpg"></p><p>
	Navigate to the Arduino sketch you want to convert.  Then press the “Open” 
button.</p><p><img src="/product_images/uploaded_images/fin-ino-file.jpg"></p><p>
	Select the appropriate board and device for your project.  In my case its 
Arduino Uno and ATmega328p.  Press the “OK” button.<br><br>
	</p><p><img src="/product_images/uploaded_images/select-board-ic.jpg"></p><p>
	You should see the project get built, and all of the libraries, include 
files, and source code will be included in the project.  The project, and how it 
is organized, is on the right.  Sketch.cpp, which is the main C++ program file 
is shown on the left.  As you open other files new tabs are added on the 
left.
	</p><p><img src="/product_images/uploaded_images/project.jpg"></p><p>
	To debug the program you need to configure the Atmel-ICE to operate in 
debugWIRE mode.  Select the Project pull down menu and at the bottom select 
“
	<em>Projectname</em> Properties…” (or click alt-F7).  Select the 
debugger/programmer tool (Atmel-ICE) and select debugWIRE from the Interface 
options.
	</p><p><img src="/product_images/uploaded_images/tool-debug.jpg"></p><p>
	You can now switch back to the Sketch.cpp tab.  Double-clicking on the margin 
left of the Sketch.cpp code will set a break point (indicated by a red dot, an 
example is shown below).  Select Debug from the run options shown in the other 
blue rectangle in the image below (under the Help menu).
	</p><p>
	Clicking on the blue run/pause icon just left of the debug option will start 
debugging.
	</p><p><img src="/product_images/uploaded_images/debug-breakpoint.jpg" alt="debug-breakpoint.jpg"></p><p>
	When you first start to debug a sketch your ATmega328p will probably not have 
correct fuse settings.  If that’s the case you will see the following message 
box.  Click the “Yes” button.</p><p><img src="/product_images/uploaded_images/fuse-message.jpg"></p><p>
	That may bring up an additional message box.  If so, toggle the power to the 
board and then press “OK”
	</p><p><img src="/product_images/uploaded_images/toggle-power.jpg"></p><p>
	You can now use AtmelStudio to step through the firmware, display variables, 
and establish breakpoints.  Here’s 
	<a href="http://www.visualmicro.com/page/Arduino-for-Atmel-Studio.aspx">one link 
that provides some information
	</a> on how to do that…</p><p>
	Exiting debugWIRE:</p><p>
	To be honest, I’m not a fan of the debugWIRE functionality, as it seems 
cumbersome and likely to brick the microcontroller from time-to-time.  Now that 
I got that off my chest, be sure that when you stop debugging you remember to 
exit debugWIRE.  Select Debug/Disable debugWIRE and Close as shown below.
	</p><p>
	NOTE:  If you don’t 
correctly exit debugWIRE the microcontroller will probably act a little quirky.  
It will do cool things like prevent you from programming the device in ISP 
mode.  I’ve recovered from this by re-entering debugWIRE mode, running the 
debugger, and then disabling debugWIRE mode as previously described.
	</p><p><img src="/product_images/uploaded_images/exit-degbugwire.jpg"></p><p>
	Restoring the Bootloader:</p><p>
	If you’re going to write code in AtmelStudio for the Arduino it seems like a 
one-way-street.  I don’t know of a way to go from an AtmelStudio project back to 
an Arduino sketch.  To be honest I didn’t look very hard, so maybe there is 
one.  As far as I’m concerned, once you’re able to debug and step through code 
using the Arduino libraries there’s not much of a reason to go back.
	</p><p>
	But you might want to use the Arduino for another project, so here are the 
steps to get the serial bootloader back into your Arduino.
	</p><p>
	You need to configure the Atmel-ICE to operate in ISP mode.  Select the 
Project pull down menu and at the bottom select the “
	<em>Projectname</em> 
Properties…”(or click alt-F7).  Select the debugger/programmer tool and select 
ISP from the Interface options.
	</p><p><img src="/product_images/uploaded_images/change-to-isp.jpg"></p><p>Select Tools/Device Programming</p><p><img src="/product_images/uploaded_images/programmig-menu.jpg"></p><p>
	Select the microcontroller you are using, for the Arduino Uno it is the 
ATmega328p.  Press the “Apply” button followed by the “Read” button.  You should 
see the device ID and the voltage show up.  If not, you could still be in 
debugWIRE mode, or you might have a bad connection somewhere.
	</p><p><img src="/product_images/uploaded_images/apply-and-read.jpg"></p><p>On&nbsp;the left side click on “Fuses”.  Enter 0x05 in the EXTENDED box, 0xDE in 
the HIGH box, and 0xFF in the LOW box.  Press the “Program” button.</p><p><img src="/product_images/uploaded_images/restore-fuses.jpg"></p><p>
	Select “Memories” from the left side of the window in focus.  Click the 
button marked with “…” and navigate to the location of the bootloader.<br><br><img src="/product_images/uploaded_images/memories-image.png" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif; font-size: 15px;">
	</p><p>Select the appropriate bootloader hex file for the Arduino you are working 
with. In my case its optiboot_atmega328.hex.&nbsp; Press "Open".
	</p><p><img src="/product_images/uploaded_images/where-is-optiboot.jpg"></p><p>Now press the “Program” button.  You’re almost back to normal.</p><p>Disconnect the Atmel-ICE from the Arduino (assuming programming 
succeeded).</p><p>
	In order to get the bootloader operating correctly you’ve got to short the 
reset pads you cut apart at the start of all this.  If you remember I added a 
header to the tinned pads.  So for me, I just need to add a jumper as shown 
below.
	</p><p><img src="/product_images/uploaded_images/arduinoing.jpg"></p><p>
	And with all that done I can now upload the original “Blink” sketch to the 
Arduino.
	</p><p><img src="/product_images/uploaded_images/blink-ino.png"></p><p>That’s it.</p>]]></description>
			<content:encoded><![CDATA[<p>
	<img src="/product_images/uploaded_images/debug-breakpoint.jpg"></p><p>
	Atmel’s Studio 7 (Atmel is now owned by Microchip) allows you to import Arduino sketches and debug 
them.  This brings the Arduino into the realm of a professional design engineer 
tool.</p><p>
	Getting an Arduino to the point of debuggin’ its 
firmware is a pretty easy process, but does take several steps.  Here are some 
things you’ll want to take note of before beginning…</p><p>
	1.  You’ll need a debugger/programmer.  I used the <a href="http://www.atmel.com/tools/atatmel-ice.aspx">Atmel-ICE</a> which retails 
for about $60US and comes with a connector compatible with the Arduino ICSP 
connection.</p><p>
	2.  I used an Arduino Uno 3.  There could be some differences between this 
Arduino and other styles.</p><p>
	3.  You’ll have to download and install <a href="http://www.atmel.com/Microsite/atmel-studio/">AtmelStudio 7</a>.  This 
development environment is based on Microsoft’s Visual Studio.  I’m pretty 
familiar with Visual Studio, so getting up to speed with AtmelStudio was not a 
problem.  I won’t go into any detail here on how to use AtmelStudio beyond 
getting a project running and recovering the Arduino.</p><p>
	4.  Speaking of recovering the Arduino… you have to make a simple hardware 
change to allow ‘debugWire’ to work with the Arduino.  Additionally, programming 
the sketch using AtmelStudio will wipe out the Arduino bootloader, so you may 
want to recover it if you intend on using the Arduino for other projects.</p><p>
	5.  It’s a good idea to read through this blog before jumping into this.  If 
you’re not comfortable with the changes you’ll be making to the Arduino you 
should probably not try this.</p><p>
	Okay, here we go…</p><p>
	Hardware Mods:The Arduino Uno 3 microcontroller, an 
ATmega328p, comes loaded with a serial bootloader (optiboot_atmega328.hex).  The 
bootloader is a program that runs on reset and programs the microcontroller’s 
memory with values sent via a serial interface.  This program is what allows 
new sketches to be uploaded to the device.  The bootloader is entered when the 
serial DTR line briefly changes state.  In the schematic clip below the line 
marked CH1 is the DTR line, and CH2 is the RESET line.
	</p><p>
	<img src="/product_images/uploaded_images/arduino-programming.jpg"></p><p>
	Here is the reset pulse captured by an oscilloscope as a sketch is uploaded 
to the Arduino.
	</p><p>
	<img src="/product_images/uploaded_images/arduino-dtr.jpg"></p><p>
	Unfortunately, C5 in the schematic impacts Atmel’s ‘debugWIRE’ debugger 
interface, which also relies on control of the ATmega328p reset line.  
Fortunately, and helpfully, the Arduino people have left a jumper cut-line on 
the PCB that allows you to disconnect C5 from the reset line.
	</p><p>
	Using a razor blade or other sharp tool cut the trace that connects the two 
tinned pads labeled ‘RESET EN’.  Be sure not to cut the trace that runs from one 
of the pads to C5.  
	NOTE… 
without this trace the Arduino will no longer be programmable with the Arduino 
software even if the bootloader is present on the microcontroller.  FYI, C5 is 
the capacitor closest to the tinned pads, and is not marked on the PCB.
	</p><p>
	<img src="/product_images/uploaded_images/cut-reset.jpg"></p><p>
	<strong><a href="file:///C:/Users/Lon/AppData/Local/Temp/WindowsLiveWriter1286139640/supfiles8F34E18C/cut_reset4.jpg"></a></strong></p><p>Once this cut is made you can proceed to debugging an Arduino sketch.  
However, I added a 2-pin header across the tinned pads that allow me to switch 
between Atmel’s ‘debugWIRE’ interface and the standard Arduino serial bootload 
mode.  This is done by removing or adding a jumper.
	</p><p><img src="/product_images/uploaded_images/ard-jumper.jpg"></p><p>
	In order to import and debug an Arduino sketch you need to do the 
following…
	</p><p>
	1.  Make sure the reset is disconnected from C5, in my case this is done by 
removing the jumper from the 2-pin header I installed.
	</p><p>
	2. Plug the Atmel-ICE 6-pin header over the 3x2 footprint marked ICSP.  The 
tab on the Atmel-ICE receptacle should face inboard (toward C5) of the Arduino 
Uno 3.  If you’re not using the Arduino Uno 3 the tab of the Atmel-ICE connector 
is on the same side of the 3x2 header as pin 1.
	</p><p>
	3. You’ll need to power the Arduino Uno through the USB or power supply 
port.
	</p><p><img src="/product_images/uploaded_images/debugging.jpg"></p><p>
	Importing and Debugging the Sketch:</p><p>
	Now that the hardware is ready you can launch AtmelStudio and begin to import 
the Arduino sketch.  In my case I’m just going to import and debug the Blink 
sketch.
	</p><p>
	Launch AtmelStudio and select New Project from the Start menu.</p><p>
	Select “Create project from Arduino sketch”.  Enter a Name, Project Name, and 
browse to where you want to keep it, then click the OK button.
	</p><p><img src="/product_images/uploaded_images/new-project-screen.jpg"></p><p>
	Navigate to the Arduino sketch you want to convert.  Then press the “Open” 
button.</p><p><img src="/product_images/uploaded_images/fin-ino-file.jpg"></p><p>
	Select the appropriate board and device for your project.  In my case its 
Arduino Uno and ATmega328p.  Press the “OK” button.<br><br>
	</p><p><img src="/product_images/uploaded_images/select-board-ic.jpg"></p><p>
	You should see the project get built, and all of the libraries, include 
files, and source code will be included in the project.  The project, and how it 
is organized, is on the right.  Sketch.cpp, which is the main C++ program file 
is shown on the left.  As you open other files new tabs are added on the 
left.
	</p><p><img src="/product_images/uploaded_images/project.jpg"></p><p>
	To debug the program you need to configure the Atmel-ICE to operate in 
debugWIRE mode.  Select the Project pull down menu and at the bottom select 
“
	<em>Projectname</em> Properties…” (or click alt-F7).  Select the 
debugger/programmer tool (Atmel-ICE) and select debugWIRE from the Interface 
options.
	</p><p><img src="/product_images/uploaded_images/tool-debug.jpg"></p><p>
	You can now switch back to the Sketch.cpp tab.  Double-clicking on the margin 
left of the Sketch.cpp code will set a break point (indicated by a red dot, an 
example is shown below).  Select Debug from the run options shown in the other 
blue rectangle in the image below (under the Help menu).
	</p><p>
	Clicking on the blue run/pause icon just left of the debug option will start 
debugging.
	</p><p><img src="/product_images/uploaded_images/debug-breakpoint.jpg" alt="debug-breakpoint.jpg"></p><p>
	When you first start to debug a sketch your ATmega328p will probably not have 
correct fuse settings.  If that’s the case you will see the following message 
box.  Click the “Yes” button.</p><p><img src="/product_images/uploaded_images/fuse-message.jpg"></p><p>
	That may bring up an additional message box.  If so, toggle the power to the 
board and then press “OK”
	</p><p><img src="/product_images/uploaded_images/toggle-power.jpg"></p><p>
	You can now use AtmelStudio to step through the firmware, display variables, 
and establish breakpoints.  Here’s 
	<a href="http://www.visualmicro.com/page/Arduino-for-Atmel-Studio.aspx">one link 
that provides some information
	</a> on how to do that…</p><p>
	Exiting debugWIRE:</p><p>
	To be honest, I’m not a fan of the debugWIRE functionality, as it seems 
cumbersome and likely to brick the microcontroller from time-to-time.  Now that 
I got that off my chest, be sure that when you stop debugging you remember to 
exit debugWIRE.  Select Debug/Disable debugWIRE and Close as shown below.
	</p><p>
	NOTE:  If you don’t 
correctly exit debugWIRE the microcontroller will probably act a little quirky.  
It will do cool things like prevent you from programming the device in ISP 
mode.  I’ve recovered from this by re-entering debugWIRE mode, running the 
debugger, and then disabling debugWIRE mode as previously described.
	</p><p><img src="/product_images/uploaded_images/exit-degbugwire.jpg"></p><p>
	Restoring the Bootloader:</p><p>
	If you’re going to write code in AtmelStudio for the Arduino it seems like a 
one-way-street.  I don’t know of a way to go from an AtmelStudio project back to 
an Arduino sketch.  To be honest I didn’t look very hard, so maybe there is 
one.  As far as I’m concerned, once you’re able to debug and step through code 
using the Arduino libraries there’s not much of a reason to go back.
	</p><p>
	But you might want to use the Arduino for another project, so here are the 
steps to get the serial bootloader back into your Arduino.
	</p><p>
	You need to configure the Atmel-ICE to operate in ISP mode.  Select the 
Project pull down menu and at the bottom select the “
	<em>Projectname</em> 
Properties…”(or click alt-F7).  Select the debugger/programmer tool and select 
ISP from the Interface options.
	</p><p><img src="/product_images/uploaded_images/change-to-isp.jpg"></p><p>Select Tools/Device Programming</p><p><img src="/product_images/uploaded_images/programmig-menu.jpg"></p><p>
	Select the microcontroller you are using, for the Arduino Uno it is the 
ATmega328p.  Press the “Apply” button followed by the “Read” button.  You should 
see the device ID and the voltage show up.  If not, you could still be in 
debugWIRE mode, or you might have a bad connection somewhere.
	</p><p><img src="/product_images/uploaded_images/apply-and-read.jpg"></p><p>On&nbsp;the left side click on “Fuses”.  Enter 0x05 in the EXTENDED box, 0xDE in 
the HIGH box, and 0xFF in the LOW box.  Press the “Program” button.</p><p><img src="/product_images/uploaded_images/restore-fuses.jpg"></p><p>
	Select “Memories” from the left side of the window in focus.  Click the 
button marked with “…” and navigate to the location of the bootloader.<br><br><img src="/product_images/uploaded_images/memories-image.png" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif; font-size: 15px;">
	</p><p>Select the appropriate bootloader hex file for the Arduino you are working 
with. In my case its optiboot_atmega328.hex.&nbsp; Press "Open".
	</p><p><img src="/product_images/uploaded_images/where-is-optiboot.jpg"></p><p>Now press the “Program” button.  You’re almost back to normal.</p><p>Disconnect the Atmel-ICE from the Arduino (assuming programming 
succeeded).</p><p>
	In order to get the bootloader operating correctly you’ve got to short the 
reset pads you cut apart at the start of all this.  If you remember I added a 
header to the tinned pads.  So for me, I just need to add a jumper as shown 
below.
	</p><p><img src="/product_images/uploaded_images/arduinoing.jpg"></p><p>
	And with all that done I can now upload the original “Blink” sketch to the 
Arduino.
	</p><p><img src="/product_images/uploaded_images/blink-ino.png"></p><p>That’s it.</p>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[PID Motor Control with an Arduino]]></title>
			<link>https://www.solutions-cubed.com/electronic-design-blog/pid-motor-control-with-an-arduino/</link>
			<pubDate>Thu, 12 Jul 2018 12:29:01 +0000</pubDate>
			<guid isPermaLink="false">https://www.solutions-cubed.com/electronic-design-blog/pid-motor-control-with-an-arduino/</guid>
			<description><![CDATA[<p>
	<img src="/product_images/uploaded_images/pid-firstbot.jpg"></p><p>PID motor control with an <a href="http://arduino.cc/" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">Arduino</a> can be accomplished using simple firmware.&nbsp; In this example we use our <a href="http://www.solutions-cubed.com/firstbot" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">Firstbot Arduino-Compatible controller</a> to implement a PID based position controller using analog feedback and a potentiometer for control.&nbsp; This is similar in operation to a hobby servo, but the potentiometer provides the control signal instead of a pulse from a receiver (and of course you are using a motor, not an RC servo).</p><p>
	<img src="/product_images/uploaded_images/firstbot-pid-thumb.jpg"></p><p>
	PID control is fairly common means of controlling a system using a well defined algorithm.&nbsp; You can learn more about the algorithm at Wikipedia (
	<a href="http://en.wikipedia.org/wiki/PID_controller" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">see PID Controller</a>). They are used in industrial control systems of all types.&nbsp; In this case I’m using it to control the position of a motor.&nbsp; I have a potentiometer that outputs a 0-5VDC control voltage.&nbsp; Attached to my motor shaft is an analog encoder that also outputs a value of 0-5VDC over a single rotation of the motor (<a href="http://www.usdigital.com/products/encoders/absolute/rotary/shaft/MA3" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">US Digital MA3 encoder</a>).&nbsp;&nbsp; The idea is that when I turn the pot the motor follows the turn and stops where the pot stops.</p><p>
	P, I, and D stand for proportional, integral, and derivative.&nbsp; Generally speaking the proportional (P) part of the control algorithm provides most of the “push” to get things moving.&nbsp; The integral (I) term is used to act on small errors and force gradual changes over time.&nbsp; The derivative (D) part of the equation acts to damp oscillations or abrupt changes in the control signal.&nbsp; The D term is usually&nbsp;works to oppose abrupt changes caused by the P term.</p><p>Here’s the code for the equation I used.&nbsp; The gain constants are set in the code, but could be made programmable through some other interface.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:4950946e-34e2-46e2-a843-622b4c580210" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>void CalculatePID(void)
{
// Set constants here
  PTerm = 2000;
  ITerm = 25;
  DTerm = 0;
  Divider = 10;

// Calculate the PID  
  Accumulator += Error[0&91;;  // accumulator is sum of errors
  PID = Error[0&91;*PTerm;     // start with proportional gain
  PID += ITerm*Accumulator; // add integral gain and error accumulation
  PID += DTerm*(Error[0&91;-Error[9&91;); // differential gain comes next</pre><p>
	Here are the major components of the PID detailed.</p><p><strong>Error Signal-</strong>&nbsp; At the heart of PID control is a need to measure an error signal.&nbsp; In this case it is the desired position (voltage from the pot) minus the actual position (voltage from the encoder).&nbsp; The error value is signed.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:8275cb7f-7843-42a9-9765-51d87714f915" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>void GetError(void)
{
  byte i = 0;

  // read analogs
  word ActualPosition = analogRead(ActPos);  

  word DesiredPosition = analogRead(DesPos);

  // shift error values
  for(i=9;i&gt;0;i--)
    Error[i&91; = Error[i-1&91;;

  // load new error into top array spot  
  Error[0&91; = (long)DesiredPosition-(long)ActualPosition;

}</pre><p><strong>PTerm –</strong>The error signal is multiplied the P term and this provides most of the “umph” behind the motor’s movement.&nbsp; A negative error signal causes the P term create a negative motor movement.&nbsp; Likewise, if my error signal is 0 then the P term has no impact on the motor.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:6fed5480-613d-4f70-aa29-cae9476571d6" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>PID = Error[0&91;*PTerm;     // start with proportional gain</pre><p><strong>ITerm –</strong> The I term is generally much smaller than the P term.&nbsp; There is also an accumulator associated with the I term.&nbsp; The accumulator sums up error signals over time.&nbsp; Eventually even small errors build up to be large number, when that happens a small I term will&nbsp; cause to move the motor.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:5c5ea9a8-a222-42a8-999e-cf41ac8edd74" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>Accumulator += Error[0&91;;  // accumulator is sum of errors
  PID += ITerm*Accumulator; // add integral gain and error accumulation</pre><p>
	In some systems it is important to prevent “windup” of the accumulator(also called saturation).&nbsp; Windup occurs when the small errors build so high that when movement finally occurs it takes a long time for the accumulator to reduce to an insignificant amount.&nbsp; I didn’t add any windup protection here, but it can often be addressed by limiting the size of the accumulator.</p><p>
	Example:</p><p>
	if (Accumulator &gt; 40000)</p><p>
	Accumulator = 40000;</p><p>
	if (Accumulator &lt; -40000)</p><p>
	Accumulator = -40000;</p><p><strong>DTerm – </strong>While I have the D term in this equation it is not used for this motor control application (see DTerm = 0 in the code).&nbsp; The D term is multiplied by the change in the error signal (error – last error).&nbsp; Sometimes it is useful to store your error measurements in an array and use as your last error something a little further back in time.&nbsp; For fast changing systems, like a motor controller, the derivative portion of the PID has little impact unless you make it very large, or compare error signals with adequate time between their sampling.&nbsp; In this code the derivative error is the latest error signal minus the 10th previous error.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:0989dd59-65ed-46b4-9f0c-3dfcdbf64816" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>PID += DTerm*(Error[0&91;-Error[9&91;); // differential gain comes next</pre><p><strong>Divider -</strong> When you put the PID together you get a pretty big value.&nbsp; This value needs to be scaled to a value that matched the pulse-width modulation range for the controller.&nbsp; The Divider does that.&nbsp; You’ll notice that the division of the PID is accomplished by right-rotates as opposed to division.&nbsp; This is just a faster way of accomplishing the same thing.&nbsp; And the faster your PID loop runs the more responsive it can be to commanded changes.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:0b1206cd-4209-43e3-a679-0286f2f813c4" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>PID = PID&gt;&gt;Divider; // scale PID down with divider</pre><p><strong>Converting the PID to PWM- </strong>Once your PID is calculated you need to change it to a motor drive signal.&nbsp; The sign of the PID output determines the direction the motor should be driven and the divider previously discussed should get you in the right neighborhood for a final number.&nbsp; Now you need to make sure the PID register contains a value that’s neither too large or too small.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:f8068afb-96e6-4860-a4c6-71f5d468ca60" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>if(PID&gt;=127)
    PID = 127;
  if(PID&lt;=-126)
    PID = -126;

//PWM output should be between 1 and 254 so we add to the PID    
  PWMOutput = PID + 127;</pre><p>
	The FIRSTBOT accepts a range of 1 to 254 (1 = full reverse, 127 = stopped, 254 = full forward).&nbsp; So we want our PID to be in the area of –126 to +127, and we’ll add 127 to it to get our 1-254 range.</p><p>
	<strong>Tuning the PID- </strong>Trail and error works.&nbsp; There are a number of methods of tuning PID algorithms, you can research those online.&nbsp; For something like a generic motor position controller using analog signals you can start by adjusting your proportional settings until you get rough control.&nbsp; If your proportional term is too high the movement will be sharp and choppy.&nbsp; If too low, it will be slow.&nbsp; This is also when you dial in the divider value to make sure your PID output falls within your PWM requirements.</p><p>
	Then increase your integral term until the final desired position is reached.&nbsp; The integral term is usually much smaller than the proportional term.&nbsp; An integral term that is too high will cause oscillations of the motor.&nbsp; Too low and it has no impact at all.&nbsp; If your motor tends to twitch you may need to add some kind of windup detection as discussed above.</p><p>
	The settings I used for this design got me to within +/-10 ADC counts within a couple of seconds.&nbsp; That is right at about 1% accuracy or 3.5 degrees for a single rotation.</p><p>
	The code has a lot of commented out print statements that can be commented in during certain tests to see what those variables look like.&nbsp; Those can be useful when tuning the PID.</p><p>
	<strong>PID Loop Time:</strong>&nbsp; You can see from this code that it is very simple.&nbsp; The serial communication that sends data to the FIRSTBOT’s other motor controller IC (a PIC16F1829) occurs every 10mS.&nbsp; Not super fast, but it certainly works for many applications.</p><p>Here’s all of the code together.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:503cd91e-4d2b-4294-9ac3-906627e6ab26" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>/*
  Firstbot PID code:  Implements a PID controller using
  analog inputs for actual and desired positions.

 The circuit: 
 * RX is digital pin 2 (connect to TX of other device)
 * TX is digital pin 3 (connect to RX of other device)

 */
#include &lt;SoftwareSerial.h&gt;

// define some constants
int ActPos = A0;    // select the input pin for feedback signal
int DesPos = A1;    // select the input pin for control signal

byte PWMOutput;
long Error[10&91;;
long Accumulator;
long PID;
int PTerm;
int ITerm;
int DTerm;
byte Divider;

/* 
The FIRSTBOT has a PIC16F1829 controller that controls the 
two MC33926 H-bridges on the board.  A oftware serial interface
is used to control that part.
*/
SoftwareSerial mySerial(2, 3); // Receive data on 2, send data on 3
byte SerialTXBuffer[5&91;;
byte SerialRXBuffer[5&91;;

void setup()  
{

 // Open serial communications and wait for port to open:
  Serial.begin(9600);
  mySerial.begin(9600);
}

/* GetError():
Read the analog values, shift the Error array down 
one spot, and load the new error value into the
top of array.
*/
void GetError(void)
{
  byte i = 0;
  // read analogs
  word ActualPosition = analogRead(ActPos);  
// comment out to speed up PID loop
//  Serial.print("ActPos= ");
//  Serial.println(ActualPosition,DEC);

  word DesiredPosition = analogRead(DesPos);
// comment out to speed up PID loop
//  Serial.print("DesPos= ");
//  Serial.println(DesiredPosition,DEC);

  // shift error values
  for(i=9;i&gt;0;i--)
    Error[i&91; = Error[i-1&91;;
  // load new error into top array spot  
  Error[0&91; = (long)DesiredPosition-(long)ActualPosition;
// comment out to speed up PID loop
//  Serial.print("Error= ");
//  Serial.println(Error[0&91;,DEC);

}

/* CalculatePID():
Error[0&91; is used for latest error, Error[9&91; with the DTERM
*/
void CalculatePID(void)
{
// Set constants here
  PTerm = 2000;
  ITerm = 25;
  DTerm = 0;
  Divider = 10;

// Calculate the PID  
  PID = Error[0&91;*PTerm;     // start with proportional gain
  Accumulator += Error[0&91;;  // accumulator is sum of errors
  PID += ITerm*Accumulator; // add integral gain and error accumulation
  PID += DTerm*(Error[0&91;-Error[9&91;); // differential gain comes next
  PID = PID&gt;&gt;Divider; // scale PID down with divider

// comment out to speed up PID loop  
//Serial.print("PID= ");
//  Serial.println(PID,DEC);

// limit the PID to the resolution we have for the PWM variable

  if(PID&gt;=127)
    PID = 127;
  if(PID&lt;=-126)
    PID = -126;

//PWM output should be between 1 and 254 so we add to the PID    
  PWMOutput = PID + 127;

// comment out to speed up PID loop
//  Serial.print("PWMOutput= ");
//  Serial.println(PWMOutput,DEC);

}

/* WriteRegister():
Writes a single byte to the PIC16F1829, 
"Value" to the register pointed at by "Index".  
Returns the response 
*/
byte WriteRegister(byte Index, byte Value)
{
byte i = 0;
byte checksum = 0;
byte ack = 0;

SerialTXBuffer[0&91; = 210;
SerialTXBuffer[1&91; = 1;
SerialTXBuffer[2&91; = 3;
SerialTXBuffer[3&91; = Index;
SerialTXBuffer[4&91; = Value;

for (i=0;i&lt;6;i++)
  {
  if (i!=5)
    {
    mySerial.write(SerialTXBuffer[i&91;);
    checksum += SerialTXBuffer[i&91;;    
    }
  else
    mySerial.write(checksum);     
  }
  delay(5);

  if (mySerial.available())
    ack = mySerial.read();

  return ack;
} 

void loop() // run over and over
{
     GetError();       // Get position error
     CalculatePID();   // Calculate the PID output from the error
     WriteRegister(9,PWMOutput);  // Set motor speed
}</pre>]]></description>
			<content:encoded><![CDATA[<p>
	<img src="/product_images/uploaded_images/pid-firstbot.jpg"></p><p>PID motor control with an <a href="http://arduino.cc/" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">Arduino</a> can be accomplished using simple firmware.&nbsp; In this example we use our <a href="http://www.solutions-cubed.com/firstbot" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">Firstbot Arduino-Compatible controller</a> to implement a PID based position controller using analog feedback and a potentiometer for control.&nbsp; This is similar in operation to a hobby servo, but the potentiometer provides the control signal instead of a pulse from a receiver (and of course you are using a motor, not an RC servo).</p><p>
	<img src="/product_images/uploaded_images/firstbot-pid-thumb.jpg"></p><p>
	PID control is fairly common means of controlling a system using a well defined algorithm.&nbsp; You can learn more about the algorithm at Wikipedia (
	<a href="http://en.wikipedia.org/wiki/PID_controller" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">see PID Controller</a>). They are used in industrial control systems of all types.&nbsp; In this case I’m using it to control the position of a motor.&nbsp; I have a potentiometer that outputs a 0-5VDC control voltage.&nbsp; Attached to my motor shaft is an analog encoder that also outputs a value of 0-5VDC over a single rotation of the motor (<a href="http://www.usdigital.com/products/encoders/absolute/rotary/shaft/MA3" style="background-color: initial; font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;">US Digital MA3 encoder</a>).&nbsp;&nbsp; The idea is that when I turn the pot the motor follows the turn and stops where the pot stops.</p><p>
	P, I, and D stand for proportional, integral, and derivative.&nbsp; Generally speaking the proportional (P) part of the control algorithm provides most of the “push” to get things moving.&nbsp; The integral (I) term is used to act on small errors and force gradual changes over time.&nbsp; The derivative (D) part of the equation acts to damp oscillations or abrupt changes in the control signal.&nbsp; The D term is usually&nbsp;works to oppose abrupt changes caused by the P term.</p><p>Here’s the code for the equation I used.&nbsp; The gain constants are set in the code, but could be made programmable through some other interface.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:4950946e-34e2-46e2-a843-622b4c580210" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>void CalculatePID(void)
{
// Set constants here
  PTerm = 2000;
  ITerm = 25;
  DTerm = 0;
  Divider = 10;

// Calculate the PID  
  Accumulator += Error[0&91;;  // accumulator is sum of errors
  PID = Error[0&91;*PTerm;     // start with proportional gain
  PID += ITerm*Accumulator; // add integral gain and error accumulation
  PID += DTerm*(Error[0&91;-Error[9&91;); // differential gain comes next</pre><p>
	Here are the major components of the PID detailed.</p><p><strong>Error Signal-</strong>&nbsp; At the heart of PID control is a need to measure an error signal.&nbsp; In this case it is the desired position (voltage from the pot) minus the actual position (voltage from the encoder).&nbsp; The error value is signed.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:8275cb7f-7843-42a9-9765-51d87714f915" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>void GetError(void)
{
  byte i = 0;

  // read analogs
  word ActualPosition = analogRead(ActPos);  

  word DesiredPosition = analogRead(DesPos);

  // shift error values
  for(i=9;i&gt;0;i--)
    Error[i&91; = Error[i-1&91;;

  // load new error into top array spot  
  Error[0&91; = (long)DesiredPosition-(long)ActualPosition;

}</pre><p><strong>PTerm –</strong>The error signal is multiplied the P term and this provides most of the “umph” behind the motor’s movement.&nbsp; A negative error signal causes the P term create a negative motor movement.&nbsp; Likewise, if my error signal is 0 then the P term has no impact on the motor.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:6fed5480-613d-4f70-aa29-cae9476571d6" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>PID = Error[0&91;*PTerm;     // start with proportional gain</pre><p><strong>ITerm –</strong> The I term is generally much smaller than the P term.&nbsp; There is also an accumulator associated with the I term.&nbsp; The accumulator sums up error signals over time.&nbsp; Eventually even small errors build up to be large number, when that happens a small I term will&nbsp; cause to move the motor.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:5c5ea9a8-a222-42a8-999e-cf41ac8edd74" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>Accumulator += Error[0&91;;  // accumulator is sum of errors
  PID += ITerm*Accumulator; // add integral gain and error accumulation</pre><p>
	In some systems it is important to prevent “windup” of the accumulator(also called saturation).&nbsp; Windup occurs when the small errors build so high that when movement finally occurs it takes a long time for the accumulator to reduce to an insignificant amount.&nbsp; I didn’t add any windup protection here, but it can often be addressed by limiting the size of the accumulator.</p><p>
	Example:</p><p>
	if (Accumulator &gt; 40000)</p><p>
	Accumulator = 40000;</p><p>
	if (Accumulator &lt; -40000)</p><p>
	Accumulator = -40000;</p><p><strong>DTerm – </strong>While I have the D term in this equation it is not used for this motor control application (see DTerm = 0 in the code).&nbsp; The D term is multiplied by the change in the error signal (error – last error).&nbsp; Sometimes it is useful to store your error measurements in an array and use as your last error something a little further back in time.&nbsp; For fast changing systems, like a motor controller, the derivative portion of the PID has little impact unless you make it very large, or compare error signals with adequate time between their sampling.&nbsp; In this code the derivative error is the latest error signal minus the 10th previous error.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:0989dd59-65ed-46b4-9f0c-3dfcdbf64816" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>PID += DTerm*(Error[0&91;-Error[9&91;); // differential gain comes next</pre><p><strong>Divider -</strong> When you put the PID together you get a pretty big value.&nbsp; This value needs to be scaled to a value that matched the pulse-width modulation range for the controller.&nbsp; The Divider does that.&nbsp; You’ll notice that the division of the PID is accomplished by right-rotates as opposed to division.&nbsp; This is just a faster way of accomplishing the same thing.&nbsp; And the faster your PID loop runs the more responsive it can be to commanded changes.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:0b1206cd-4209-43e3-a679-0286f2f813c4" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>PID = PID&gt;&gt;Divider; // scale PID down with divider</pre><p><strong>Converting the PID to PWM- </strong>Once your PID is calculated you need to change it to a motor drive signal.&nbsp; The sign of the PID output determines the direction the motor should be driven and the divider previously discussed should get you in the right neighborhood for a final number.&nbsp; Now you need to make sure the PID register contains a value that’s neither too large or too small.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:f8068afb-96e6-4860-a4c6-71f5d468ca60" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>if(PID&gt;=127)
    PID = 127;
  if(PID&lt;=-126)
    PID = -126;

//PWM output should be between 1 and 254 so we add to the PID    
  PWMOutput = PID + 127;</pre><p>
	The FIRSTBOT accepts a range of 1 to 254 (1 = full reverse, 127 = stopped, 254 = full forward).&nbsp; So we want our PID to be in the area of –126 to +127, and we’ll add 127 to it to get our 1-254 range.</p><p>
	<strong>Tuning the PID- </strong>Trail and error works.&nbsp; There are a number of methods of tuning PID algorithms, you can research those online.&nbsp; For something like a generic motor position controller using analog signals you can start by adjusting your proportional settings until you get rough control.&nbsp; If your proportional term is too high the movement will be sharp and choppy.&nbsp; If too low, it will be slow.&nbsp; This is also when you dial in the divider value to make sure your PID output falls within your PWM requirements.</p><p>
	Then increase your integral term until the final desired position is reached.&nbsp; The integral term is usually much smaller than the proportional term.&nbsp; An integral term that is too high will cause oscillations of the motor.&nbsp; Too low and it has no impact at all.&nbsp; If your motor tends to twitch you may need to add some kind of windup detection as discussed above.</p><p>
	The settings I used for this design got me to within +/-10 ADC counts within a couple of seconds.&nbsp; That is right at about 1% accuracy or 3.5 degrees for a single rotation.</p><p>
	The code has a lot of commented out print statements that can be commented in during certain tests to see what those variables look like.&nbsp; Those can be useful when tuning the PID.</p><p>
	<strong>PID Loop Time:</strong>&nbsp; You can see from this code that it is very simple.&nbsp; The serial communication that sends data to the FIRSTBOT’s other motor controller IC (a PIC16F1829) occurs every 10mS.&nbsp; Not super fast, but it certainly works for many applications.</p><p>Here’s all of the code together.</p><p id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:503cd91e-4d2b-4294-9ac3-906627e6ab26" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"></p><pre>/*
  Firstbot PID code:  Implements a PID controller using
  analog inputs for actual and desired positions.

 The circuit: 
 * RX is digital pin 2 (connect to TX of other device)
 * TX is digital pin 3 (connect to RX of other device)

 */
#include &lt;SoftwareSerial.h&gt;

// define some constants
int ActPos = A0;    // select the input pin for feedback signal
int DesPos = A1;    // select the input pin for control signal

byte PWMOutput;
long Error[10&91;;
long Accumulator;
long PID;
int PTerm;
int ITerm;
int DTerm;
byte Divider;

/* 
The FIRSTBOT has a PIC16F1829 controller that controls the 
two MC33926 H-bridges on the board.  A oftware serial interface
is used to control that part.
*/
SoftwareSerial mySerial(2, 3); // Receive data on 2, send data on 3
byte SerialTXBuffer[5&91;;
byte SerialRXBuffer[5&91;;

void setup()  
{

 // Open serial communications and wait for port to open:
  Serial.begin(9600);
  mySerial.begin(9600);
}

/* GetError():
Read the analog values, shift the Error array down 
one spot, and load the new error value into the
top of array.
*/
void GetError(void)
{
  byte i = 0;
  // read analogs
  word ActualPosition = analogRead(ActPos);  
// comment out to speed up PID loop
//  Serial.print("ActPos= ");
//  Serial.println(ActualPosition,DEC);

  word DesiredPosition = analogRead(DesPos);
// comment out to speed up PID loop
//  Serial.print("DesPos= ");
//  Serial.println(DesiredPosition,DEC);

  // shift error values
  for(i=9;i&gt;0;i--)
    Error[i&91; = Error[i-1&91;;
  // load new error into top array spot  
  Error[0&91; = (long)DesiredPosition-(long)ActualPosition;
// comment out to speed up PID loop
//  Serial.print("Error= ");
//  Serial.println(Error[0&91;,DEC);

}

/* CalculatePID():
Error[0&91; is used for latest error, Error[9&91; with the DTERM
*/
void CalculatePID(void)
{
// Set constants here
  PTerm = 2000;
  ITerm = 25;
  DTerm = 0;
  Divider = 10;

// Calculate the PID  
  PID = Error[0&91;*PTerm;     // start with proportional gain
  Accumulator += Error[0&91;;  // accumulator is sum of errors
  PID += ITerm*Accumulator; // add integral gain and error accumulation
  PID += DTerm*(Error[0&91;-Error[9&91;); // differential gain comes next
  PID = PID&gt;&gt;Divider; // scale PID down with divider

// comment out to speed up PID loop  
//Serial.print("PID= ");
//  Serial.println(PID,DEC);

// limit the PID to the resolution we have for the PWM variable

  if(PID&gt;=127)
    PID = 127;
  if(PID&lt;=-126)
    PID = -126;

//PWM output should be between 1 and 254 so we add to the PID    
  PWMOutput = PID + 127;

// comment out to speed up PID loop
//  Serial.print("PWMOutput= ");
//  Serial.println(PWMOutput,DEC);

}

/* WriteRegister():
Writes a single byte to the PIC16F1829, 
"Value" to the register pointed at by "Index".  
Returns the response 
*/
byte WriteRegister(byte Index, byte Value)
{
byte i = 0;
byte checksum = 0;
byte ack = 0;

SerialTXBuffer[0&91; = 210;
SerialTXBuffer[1&91; = 1;
SerialTXBuffer[2&91; = 3;
SerialTXBuffer[3&91; = Index;
SerialTXBuffer[4&91; = Value;

for (i=0;i&lt;6;i++)
  {
  if (i!=5)
    {
    mySerial.write(SerialTXBuffer[i&91;);
    checksum += SerialTXBuffer[i&91;;    
    }
  else
    mySerial.write(checksum);     
  }
  delay(5);

  if (mySerial.available())
    ack = mySerial.read();

  return ack;
} 

void loop() // run over and over
{
     GetError();       // Get position error
     CalculatePID();   // Calculate the PID output from the error
     WriteRegister(9,PWMOutput);  // Set motor speed
}</pre>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[A Peltier Module Temperature Chamber]]></title>
			<link>https://www.solutions-cubed.com/electronic-design-blog/a-peltier-module-temperature-chamber/</link>
			<pubDate>Tue, 10 Jul 2018 12:30:51 +0000</pubDate>
			<guid isPermaLink="false">https://www.solutions-cubed.com/electronic-design-blog/a-peltier-module-temperature-chamber/</guid>
			<description><![CDATA[<p><img src="/product_images/uploaded_images/temp-chamber.png"></p><p>One of our interns built a “hot box” out of wood a few years ago.  What’s a 
“hot box” you ask?  Beyond something you’d find in a Paul Newman prison flick,  
its pretty much a poor man’s temperature chamber. Except the temperatures only 
go up from ambient.  I’ve been surprised how often we use it, and how well it 
has held up, considering it was put together with wire-wrap and  off-the-shelf 
development boards.  But I’ve decided to take that old axiom “if it ain’t broke 
don’t fix it” and throw it out the window.</p><p>I’ve decided to go ahead and re-design it.  I guess I could list a few 
reasons for embarking on the project but it really comes down to a desire to 
explore some technology I haven’t designed with before.  The heart of my 
temperature control box will be <a href="https://en.wikipedia.org/wiki/Thermoelectric_effect">Peltier</a> modules.  </p><p>Not too long ago we were working on a laser based system in a food production 
facility.  The factory floor where our system lived was subject to a wide range 
of temperatures and humidity.  It was apparent early on that the laser 
electronics could reach shutdown temperatures during hot summer days.  So the 
electronics needed to be cooled.  To keep the laser running a thermoelectric air 
conditioning system was installed.  This was a great solution because it didn’t 
require chemicals (something you need to keep away from food), controlled a 
small chamber’s temperature, and had access to all the electrical power a 
factory could provide.  But we didn’t design the cooling system.  We just 
suggested it as an option, and our customer purchased and installed it.</p><p>I wanted to bring some if this “coolness” to our “hot box”, and maybe give us 
an option to cycle our electronic designs through temperatures from 0-100C, 
instead of just higher than the ambient office temperature.  Peltier modules 
allow you to generate a hot and cold side based on the direction of current 
flow.  You can also vary the voltage across them to control how hot or cold they 
get.  In a sense they are like dc motors, where forward/reverse and speed are 
analogous to heating/cooling and the differential in temperatures of the two 
surfaces of the Peltier module.</p><p>One option to control a Peltier module is to use an H-bridge where the 
pulse-width-modulation output is filtered through a large capacitor (creating a 
proportional DC voltage).  Since temperature changes pretty slowly, I opted to 
replace the H-bridge with relays.  Rather than control the voltage across the 
Peltier module directly, I’ll control the duty cycle of the relay “on” time.  
For example, during heating I might heat for 45 seconds, out of every minute.  
This will allow the heat sinks and fans on the modules to keep the temperature 
differential between the hot and cold sides below the maximum the module 
allows.  The schematic below shows a portion of the temperature chamber 
microcontroller that controls the voltage polarity across the Peltier module.  </p><p><img src="/product_images/uploaded_images/temp-chamber-relay-schematic.png"></p><p><img src="/product_images/uploaded_images/temperature-chamber-electronic-mechanics.png"></p>]]></description>
			<content:encoded><![CDATA[<p><img src="/product_images/uploaded_images/temp-chamber.png"></p><p>One of our interns built a “hot box” out of wood a few years ago.  What’s a 
“hot box” you ask?  Beyond something you’d find in a Paul Newman prison flick,  
its pretty much a poor man’s temperature chamber. Except the temperatures only 
go up from ambient.  I’ve been surprised how often we use it, and how well it 
has held up, considering it was put together with wire-wrap and  off-the-shelf 
development boards.  But I’ve decided to take that old axiom “if it ain’t broke 
don’t fix it” and throw it out the window.</p><p>I’ve decided to go ahead and re-design it.  I guess I could list a few 
reasons for embarking on the project but it really comes down to a desire to 
explore some technology I haven’t designed with before.  The heart of my 
temperature control box will be <a href="https://en.wikipedia.org/wiki/Thermoelectric_effect">Peltier</a> modules.  </p><p>Not too long ago we were working on a laser based system in a food production 
facility.  The factory floor where our system lived was subject to a wide range 
of temperatures and humidity.  It was apparent early on that the laser 
electronics could reach shutdown temperatures during hot summer days.  So the 
electronics needed to be cooled.  To keep the laser running a thermoelectric air 
conditioning system was installed.  This was a great solution because it didn’t 
require chemicals (something you need to keep away from food), controlled a 
small chamber’s temperature, and had access to all the electrical power a 
factory could provide.  But we didn’t design the cooling system.  We just 
suggested it as an option, and our customer purchased and installed it.</p><p>I wanted to bring some if this “coolness” to our “hot box”, and maybe give us 
an option to cycle our electronic designs through temperatures from 0-100C, 
instead of just higher than the ambient office temperature.  Peltier modules 
allow you to generate a hot and cold side based on the direction of current 
flow.  You can also vary the voltage across them to control how hot or cold they 
get.  In a sense they are like dc motors, where forward/reverse and speed are 
analogous to heating/cooling and the differential in temperatures of the two 
surfaces of the Peltier module.</p><p>One option to control a Peltier module is to use an H-bridge where the 
pulse-width-modulation output is filtered through a large capacitor (creating a 
proportional DC voltage).  Since temperature changes pretty slowly, I opted to 
replace the H-bridge with relays.  Rather than control the voltage across the 
Peltier module directly, I’ll control the duty cycle of the relay “on” time.  
For example, during heating I might heat for 45 seconds, out of every minute.  
This will allow the heat sinks and fans on the modules to keep the temperature 
differential between the hot and cold sides below the maximum the module 
allows.  The schematic below shows a portion of the temperature chamber 
microcontroller that controls the voltage polarity across the Peltier module.  </p><p><img src="/product_images/uploaded_images/temp-chamber-relay-schematic.png"></p><p><img src="/product_images/uploaded_images/temperature-chamber-electronic-mechanics.png"></p>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Visit our blog]]></title>
			<link>https://www.solutions-cubed.com/visit-our-blog/</link>
			<pubDate>Mon, 22 Jul 2013 12:41:28 +0000</pubDate>
			<guid isPermaLink="false">https://www.solutions-cubed.com/visit-our-blog/</guid>
			<description><![CDATA[<p><a href="http://blog.solutions-cubed.com" target="_blank"><img class="__mce_add_custom__" title="blog-page-600x360.jpg" src="https://www.solutions-cubed.com/product_images/uploaded_images/blog-page-600x360.jpg" alt="blog-page-600x360.jpg" width="600" height="360" /></a><br />Visit our blog, <span style="text-decoration: underline;"><a href="http://blog.solutions-cubed.com" target="_blank">blog.solutions-cubed.com</a></span>, for our latest posts,&nbsp;where we cover things like&nbsp;near field communication (NFC), tilt-compensated electronic compass code, and motor control methods.</p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.solutions-cubed.com" target="_blank"><img class="__mce_add_custom__" title="blog-page-600x360.jpg" src="https://www.solutions-cubed.com/product_images/uploaded_images/blog-page-600x360.jpg" alt="blog-page-600x360.jpg" width="600" height="360" /></a><br />Visit our blog, <span style="text-decoration: underline;"><a href="http://blog.solutions-cubed.com" target="_blank">blog.solutions-cubed.com</a></span>, for our latest posts,&nbsp;where we cover things like&nbsp;near field communication (NFC), tilt-compensated electronic compass code, and motor control methods.</p>]]></content:encoded>
		</item>
	</channel>
</rss>
