tag:blogger.com,1999:blog-74438037995144479022024-03-05T12:52:19.126-05:00The Pi & IMy Experiences With the Raspberry Pi -- Tracking My Learning -- My Pi ProjectsMartyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.comBlogger51125tag:blogger.com,1999:blog-7443803799514447902.post-48393641486455801142016-08-28T14:29:00.000-04:002016-08-28T14:29:23.978-04:00ATmega328P and the Serial Peripheral Interface<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<h3>Introduction</h3>
<div style="margin-bottom: 0.1in;">This post continues my discussion of register programming of the ATmega328P microcontroller. Specifically, the ATmega's Serial Peripheral Interface, commonly just called SPI. It also continues the discussion of my large LED display from my last blog post. </div>
<h3>My Display</h3>
<div style="margin-bottom: 0.1in;">I have a five row by ninety column LED display. What would be the best way to deal with the content I wish to display? I could hard code the message in a variable. That's fine if I don't ever want to change the message. I also run into the 2 kbytes SRAM memory limitation of the ATmega328P. I have several different messages to display and would like to add, delete, and edit messages. I also display dynamic messages like the ever changing weather. In fact, if you look at my last post you see I display the current weather and weather forecasts from Weather Underground. I get weather updates every 10 minutes. I don't need to update any more often, and there is a limit to the number of accesses I can make without incurring a charge. Therefore, I need to continuously display the same information until I get an update. The best way to handle all of these issues is to store all messages in another memory device - a nonvolatile memory, of course. </div>
<div style="margin-bottom: 0.1in;">My nonvolatile memory is a 25AA512 serial EEPROM. This eight pin IC contains 64 kilobytes of memory and has builtin SPI. This is perfect, both the serial EEPROM and the ATmega328P have SPI. The Arduino IDE comes with an SPI library that looks pretty comprehensive. But, I just feel more comfortable programming the applicable ATmega328P registers. I have more confidence that I can successfully get the two devices talking to each other. Besides, the Arduino library has limitations.</div>
<div style="margin-bottom: 0.1in;">You can see the serial EEPROM sitting to the right if the ATmega328P on my interface board. Look towards the bottom of my last post.</div>
<h3>The SPI</h3>
<div style="margin-bottom: 0.1in;">The SPI, or Serial Peripheral Interface is really quite simple. It's not good for long distances but can be reasonably fast. It always involves one master device and one or more slave devices. The master is in complete control. The slaves do not start a conversation, which is just fine when the slave is a serial EEPROM. The master talks to only one slave at a time. </div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNdVahrRnA-IDkTZo08VlhySilc9vN28FZYHgiSd9ayUb73gNsfN608tFry3VCRoFfH4IvupMFNA9jHJDeKHm0cVoiegodyIMHP3drBUaf4q_hABl9Cyors8iTSY5RovecG_xb0rsLWy9m/s1600/SPI_BlockDiagram1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNdVahrRnA-IDkTZo08VlhySilc9vN28FZYHgiSd9ayUb73gNsfN608tFry3VCRoFfH4IvupMFNA9jHJDeKHm0cVoiegodyIMHP3drBUaf4q_hABl9Cyors8iTSY5RovecG_xb0rsLWy9m/s600/SPI_BlockDiagram1.jpg" /></a></div></div>
<div style="margin-bottom: 0.1in;">There are four signal lines<b>:</b></div>
<ul>
<li>SCK, for Serial clock
<li>MISO, for Master In, Slave Out
<li>MOSI, for Master out, Slave in
<li>SS, for Slave Select
</ul>
<div style="margin-bottom: 0.1in;">The master and all slaves connect to SCK, MISO, and MOSI. However, each slave must receive its own SS connection from the master. </div>
<div style="margin-bottom: 0.1in;">The master contains a clock generator, a shift register, and control circuitry. Each slave has its own shift register. The slave, if it sees its SS line active, uses the clock from the master (SCK) to shift out the data in its shift register onto MISO. At the same time, it shifts in data from the master, on MOSI, into the same shift register. If it does not find SS active it keep its MISO in a high impedance state, allowing other slaves access to MISO. </div>
<div style="margin-bottom: 0.1in;">When the master wishes to write to, or read from, a slave, it brings that particular slave's slave select (SS) line to a logic low. The master will send eight clock pulses to its shift register to shift out the byte of data that was previously stored in its shift register. Each bit appears on MOSI. As each bit is clocked out on MOSI, a bit is simultaneously clocked in from the active slave on MISO. </div>
<div style="margin-bottom: 0.1in;">On the slave side, SS low, allows the SCK clock from the master to be passed to the slave's shift register and takes the shift register output out of a tristate (or open drain). Each clock pulse, clocks out the contents of the slave shift register onto MISO, while clocking data in from the master on MOSI. When the data transfer is complete, the master brings SS high again. </div>
<div style="margin-bottom: 0.1in;">It is possible for multiple bytes to be transferred while SS is low. The clock runs for eight pulses, the shift register is loaded with a new byte and the clock runs for eight cycles again. This is repeated until the entire message is sent or received. The transfer is completed by bring SS high.</div>
<h3>SPI Options</h3>
<div style="margin-bottom: 0.1in;">There is flexibility built into the SPI. The designer of a device can choose how it's implemented. As stated before, data will be sampled (clocked in), and outputted (clocked out), simultaneously on both MOSI and MISO. The two operations will be done on opposite edges of SCK. The designer can choose to output on the rising edge and sample on the falling edge, or output on the falling edge and sample on the rising edge. The master and slaves must use the same selection. </div>
<div style="margin-bottom: 0.1in;">In SPI parlance, this is controlled by two parameters (not part of the specification, but most manufactures comply with these definitions), CPOL, and CPHA. As follows<b>:</b> </div>
<ul>
<li>CPOL<b>:</b> Polarity of the clock when in an idle state. CPOL = 0, if SCK is low at idle. CPOL = 1, if SCK is high at idle
<li>CPHA<b>:</b> Cock Phase. CPHA = 0, if data is sampled on the rising edge of the clock and output on the falling edge of the clock. CPHA = 1 if data is sampled on the falling edge of the clock and output on the rising edge of the clock.
</ul>
<div style="margin-bottom: 0.1in;"> The combination of the clock polarity at idle and the edge to sample and clock out comprises four modes (most manufacturers comply with this)<b>:</b></div>
<ul>
<li>MODE 0<b>:</b> CPOL = 0, CPHA = 0
<li>MODE 1<b>:</b> CPOL = 0, CPHA = 1
<li>MODE 2<b>:</b> CPOL = 1, CPHA = 0
<li>MODE 3<b>:</b> CPOL = 1, CPHA = 1
</ul>
<div style="margin-bottom: 0.1in;"><b>A diagram is in order:</b></div>
<div class="separator" style="clear: both; text-align: center;"><iframe src="https://drive.google.com/file/d/0B8bfN-QZGBgyTC11bDUyLXl1TTA/preview" width="600" height="520"></iframe><div class = "caption"><font color = "blue"><i><center></i></center></font color></div><b>SPI Modes</b></div>
<div style="margin-bottom: 0.1in;">Notice that as soon as SS goes low, a bit, either the MSB or the LSB of the master's shift register, and the selected slave's shift register, will appear on MOSI, and MISO respectively. With CPHA = 0, that bit will be the first bit of the requested data. With CPHA = 1, the first bit of requested data does not appear until the first clock transition. </div>
<div style="margin-bottom: 0.1in;"><b>Another Option:</b> Notice in the diagram the bit names like "BIT 0 or 7". Another option the user has is to determine how the bits are shifted out - either LSB (BIT 0) first or MSB (BIT 7) first.</div>
<div style="margin-bottom: 0.1in;">Another option available to the user may be the selection of the clock frequency.</div>
<h3>SPI Implementation Using the ATmega328P and the Serial EEPROM</h3>
<h4>Serial EEPROM Requirements</h4>
<div style="margin-bottom: 0.1in;">The 25AA512's SPI bus has definite requirements. You could say that the ATmega328P master is a slave to the slave's requirements. Therefore, the place to start is with the <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/22021F.pdf">25AA512's data sheet, as seen here.</a> </div>
<div style="margin-bottom: 0.1in;">The first thing that jumps out at you is that the data sheet does not use the expected pin nomenclature. While they use SCK, there is no MOSI, MISO, or SS. How then do you know that the thing has an SPI? It tell you so. On the first page under "Description" is says, "The memory is accessed via a simple Serial Peripheral Interface (SPI) compatible serial bus.". That's pretty definitive. Their pin definition is as follows: SCK is SCK, MOSI is SI (slave in), MISO is SO (slave out), and SS is CS (chip select). </div>
<div style="margin-bottom: 0.1in;">You don't see the terms CPOL, CPHA, or MODE 0, MODE 1, MODE 2, or MODE 3. This means you have to figure it out for yourself. Luckily, it's obvious. On page 8, Figure 2-1, you see that the clock, SCK, is low when idle, therefore CPOL is 0. The data bits on SI and SO line up with the falling edge of SCK, therefore CPHA is also 0. This equates to Mode 0. The figure also tells you that the most significant bit is available first on SO, and it expects the most significant bit first from the master on SI. </div>
<div style="margin-bottom: 0.1in;">To see the maximum clock speed, you need to look at the AC characteristics and the timing diagrams. The maximum clock frequency is 20 MHz with a VCC of 5V. </div>
<div style="margin-bottom: 0.1in;">There is a lot more information in the data sheet you need to know. For every operation (read, write, erase), there is an instruction that must first be sent to the device. See Table 2-1. Every operation you can do is detailed in the data sheet. You also learn that you can read and write multiple bytes before bringing SS high. However, when writing data you can not cross over to another page when writing multiple bytes. </div>
<h4>Programming the ATmega328P</h4>
<div style="margin-bottom: 0.1in;">Here is a fragment of code taken from several sketches and distilled down to only reference communicating with the serial EEPROM by the SPI.<a href="https://github.com/RaspPiGuy/Weather-Displayed-On-LED-Display---ATmega-and-ESP12-Project/tree/master/Arduino%20Sketches"> Here is a link to all the Arduino sketches I wrote for the display.</a> </div>
<script src="https://gist.github.com/RaspPiGuy/299cf749fb766ff32a2eb48b8d42313e.js"></script>
<div style="margin-bottom: 0.1in;">The sketch only includes some #defines and functions. Looking at the function, initializeSPI(), there is a great deal of information in the comments. You can see the ATmega pin assignments on port B used for SPI. To use the built-in SPI of the ATmega328P, SCK, MISO, and MOSI must use the pins as stipulated in the comments. SS does not necessarily have to be on PB2 if the ATmega is the master. If the ATmega is the slave, then SS must be on PB2. In our case, the ATmega is the master.</div>
<div style="margin-bottom: 0.1in;">There are #defines at the top. The ones under "Serial EEPROM Instructions" come directly from the 25AA512 data sheet, table 2-1 on page 7. SLAVE_SELECT definition relates to the pin on port B, pin PB2 which is the SS pin. . </div>
<div style="margin-bottom: 0.1in;">There are three registers within the ATmega328P related to SPI. See section 23.5 of the <a href="http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf">ATmega328P data sheet</a> for details of each register<b>:</b> </div>
<ul>
<li>SPCR: SPI Control Register
<li>SPSR: SPI Status Register
<li>SPDR: SPI Data Register
</ul>
<div style="margin-bottom: 0.1in;">The comments, "Setting the Control Register, SPCR" shows the choices I made for my project. Notice bits 0, and 1 set SCK frequency to 4MHz. </div>
<div style="margin-bottom: 0.1in;">SPDR is the register that holds the data. Basically, SPDR acts as the shift register. SPSR is the status register. We are only interested in one bit of SPSR, the SPIF bit. This is the SPI interrupt flag. When the transfer of a byte is complete (eight clocks), this bit is set. If enabled (not so in my project), an interrupt will also occur. </div>
<div style="margin-bottom: 0.1in;">The operation of transferring a byte over SPI is contained in my function "SPIoperation()". This function is used for both sending data to the serial EEPROM and reading from the serial EEPROM, Loading a byte of data into SPDR starts the data transfer process. Even if our intention is to read data, we must send send a byte of data. Next, we simply poll SPSR looking for SPIF to be set. When that occurs, we can simply read SPDR to see what was returned from the serial EEPROM. Pretty simple. </div>
<div style="margin-bottom: 0.1in;">The last function "readFromSerialEEPROM()" shows the read process. We send it an address (16 bits) of the location in the serial EEPROM containing the first byte of data we wish to read. We also send it the number of bytes we want to read. We set SS low to start things off. We then write three bytes to the serial EEPROM ignoring what is returned. The first byte is the "READ" instruction. The next two bytes are the upper and lower bytes of the address. After that we simply send something the serial EEPROM will ignore (0xFF) and read a byte from the serial EEPROM. Every time we send 0xFF, the serial EEPROM will increment its address counter and send back a new byte. After reading the number of bytes requested, we bring SS high.</div>
<div style="margin-bottom: 0.1in;">Writing to the serial EEPROM is similar but a little more involved. Note the function "writeToSerialEEPROM(). We send this what we want to store in the serial EEPROM as a String object (my choice here. You can also send it an array of characters). We also send it the number of bytes to store and the starting address in the serial EEPROM. Firs,t we must convert the String to an array of characters. </div>
<div style="margin-bottom: 0.1in;">The memory of the 25AA512 is organized into 128 byte pages. You can write into consecutive addresses, like you can read from consecutive addresses, as is done in my read function. However, unlike a read, you can not cross a page boundary when you write. Taking an example, if you wish to write 129 bytes starting at byte 0, by taking advantage of the consecutive write feature, the 129th byte will not go into address 128, it will go into address 0, overwriting what you put there first. </div>
<div style="margin-bottom: 0.1in;">The write process also starts by bringing SS low. We follow that by write four bytes to the serial EEPROM, WREN (write enable), WRITE, and the upper and lower bytes of the starting address. Next, we can write consecutive bytes, but we have to monitor the address we are going to write to. If that address is a multiple of 128 we are at the page boundary. In that case we must bring SS high, bring SS low, send WREN, WRITE, and the new address, before writing more bytes of data. When you have written the last byte, SS can be brought high again. </div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-80779652808663156052016-08-01T14:28:00.000-04:002016-08-14T16:22:35.149-04:00ESP8266 - Downloading Weather To LED Display<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<h3>Introduction</h3>
<div style="margin-bottom: 0.1in;">My electronic endeavors, lately, have taken me down two paths. One path was dealing with a salvaged LED display, and the other was the ESP8266. Those paths have now been joined in a challenging project. </div>
<div style="margin-bottom: 0.1in;">Here is a video of the project:</div>
<div style="margin-bottom: 0.1in;"><iframe width="560" height="315" src="https://www.youtube.com/embed/_Wsy6sjDdTc" frameborder="0" allowfullscreen></iframe></div>
<h3>All Design Documentation</h3>
<div style="margin-bottom: 0.1in;">All of my design files including schematics, board layout, and all programming sketches are on my <a href="https://github.com/RaspPiGuy/Weather-Displayed-On-LED-Display---ATmega-and-ESP12-Project">GitHub repository</a>. There is an extensive readme file with plenty if details. </div>
<h3>The Display</h3>
<div style="margin-bottom: 0.1in;">Sometime ago a friend gave me a board with 18 five column by seven row LED matrices, Thanks Mike.<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrI3xzvxwyZQd0g40vPCkeCwCrynIPcWLwoiEMW6IuCEIdi7S42Lusa-Mu6reUv7_yVQcNmTXqGrOl-R-O0dyLrX-I-OL9pIxvGtnmXZ5r85aGDPv0W2khLBbhaoyvhPfc0dcx2JhAMnHf/s1600/LED+Display+Module.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrI3xzvxwyZQd0g40vPCkeCwCrynIPcWLwoiEMW6IuCEIdi7S42Lusa-Mu6reUv7_yVQcNmTXqGrOl-R-O0dyLrX-I-OL9pIxvGtnmXZ5r85aGDPv0W2khLBbhaoyvhPfc0dcx2JhAMnHf/s560/LED+Display+Module.jpg" width="560" height="116" /></a></div></div>
<div style="margin-bottom: 0.1in;">The board was missing the four most critical ICs, namely the microprocessor and two RAM chips. I'm guessing the forth IC was a programmable read only memory used to translate ASCII characters to row and column bit patterns - a character generator.</div>
<div style="margin-bottom: 0.1in;">I probably would have removed those ICs anyway.</div>
<div style="margin-bottom: 0.1in;">Fortunately, I had enough information to reverse engineer the display PCB and was able to design an interface board using an ATmega328P microprocessor. The ATmega device has enough internal SRAM and an internal EEPROM. I built my character generator in the EEPROM. You can see that interface board and its connections to the display PCB as the still shot for the video.</div>
<div style="margin-bottom: 0.1in;">There are 90 columns and the most typical programming scheme would be to start at one end, load the column data for one column, turn that column on, then move down the line doing the same for each column. Each individual LED would be accessed 1/90 of the time. This display PCB divided the columns into six zones. The data for six columns are loaded and all six columns turned on simultaneously. An individual LED is accessed 1/15 of the time. If an LED is meant to be on, it will be six times brighter. </div>
<div style="margin-bottom: 0.1in;">I wrote Arduino sketch for the user to write messages to a serial EEPROM on my interface board, and select one of 28 possible messages stored in the EEPROM to display. I wrote separate sketches to display in four direction<b>:</b> </div>
<ul>
<li>from right to left which I call my Times Square Scroll
<li>from left to right. Challenge here was that the letters in each word had to be reversed, otherwise "the" would become "eht"
<li>from top to bottom. My favorite. Challenge was to not split up words between lines. See second video in my youtobe video, above.
<li>from bottom to top. Like top to bottom with the same challenge
</ul>
<div style="margin-bottom: 0.1in;">I wanted the display to do more, to be dynamic, to display stuff I did not write - like the weather or latest news. </div>
<h3>ESP8266</h3>
<div style="margin-bottom: 0.1in;">At the same time, while working on the display, I got on the ESP8266 bandwagon. One of the limitations of the Arduino platform was realistic WiFi access. There Arduino are shields like the Xbee series of boards, but they are pretty expensive. </div>
<div style="margin-bottom: 0.1in;">Along came a tiny 8 pin PCB from China:</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: right; float: left; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvthVe6ey922l1DZmXFDKt-jT6Wxzg81BDoIV3HlA_FSlpaswSMdnSOnjixt3XFp0WHyIslb-ickD7Wv2h9BD2UDUtFnIGNaKXBL8eMp0S1FVL9fhaoRo_hatw5NEh4OLM0zt3gyeyAQI4/s1600/WiFi+Serial+Transceiver+Module.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvthVe6ey922l1DZmXFDKt-jT6Wxzg81BDoIV3HlA_FSlpaswSMdnSOnjixt3XFp0WHyIslb-ickD7Wv2h9BD2UDUtFnIGNaKXBL8eMp0S1FVL9fhaoRo_hatw5NEh4OLM0zt3gyeyAQI4/s320/WiFi+Serial+Transceiver+Module.jpg" width="160" height="120" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>ESP8266 / ESP-1</a></div></div>
<div style="margin-bottom: 0.1in;">This device is a little less than an inch long and a little over one half inch wide. I have seen it being sold for $2.40 USD. The small 32 pin IC is the ESP8266 chip itself. It contains a very capable microcontroller along with the WiFi circuitry - everything but the antenna. The antenna is those wavy lines at the top of the board. I happened to come across a YouTube video from electronupdate where the ESP8266 was photomicrographed. Here is what it looks like inside. </div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; float: right; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHncqBaLFeF3cPkfstUDdZIP-OuEHaeo-lE6gIhaORL21T-4ezrjZ_uGXrmUeJ4WllW_i1vkJZyXZsOqEYLLWWC1SNNSzPfHr4tjPOKxpCq2WfIraE3gbl6ScXL9D7AFeoAf7BbSLS_aMT/s1600/Inside+the+ESP8266.JPG" imageanchor="1" style="clear: both; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHncqBaLFeF3cPkfstUDdZIP-OuEHaeo-lE6gIhaORL21T-4ezrjZ_uGXrmUeJ4WllW_i1vkJZyXZsOqEYLLWWC1SNNSzPfHr4tjPOKxpCq2WfIraE3gbl6ScXL9D7AFeoAf7BbSLS_aMT/s120/Inside+the+ESP8266.JPG" width="120" height="148" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>Inside the ESP8266</a></div></div>
<div style="margin-bottom: 0.1in;">All the red is the logic circuitry for the microcontroller. All the rest is for the Wi-Fi. You can recognize inductors in the picture - those oval items. The eight pin device is a 8 Mbit serial Flash Memory with an SPI. </div>
<div style="margin-bottom: 0.1in;">Although this module is commonly called an ESP8266, its proper name is the ESP-1. It has a couple of limitations. There is only one useful I/O pin and it's not RFI shielded. The pins do have a 0.1" pitch which is nice for mounting on vectorboards. </div>
<div style="margin-bottom: 0.1in;">There are newer generations using the same ESP8266 integrated circuit. The latest seems to be the ESP-14, but the most common seems to be the ESP-12, of which the ESP-12f is the latest flavor. I'm familiar with the ESP-12e, so will not talk about the ESP-14 (same WiFi as in ESP8266 but another microcontroller). the advantages of the ESP-12 are seven fully useful I/O pins, and FCC certified RFI shielding. It does have 2mm pitch castellated pads though. While designed for surface mount placement, I have been able to solder 24AWG solid wire through the holes to connect to other circuitry. I have seen a price of $2.50 USD for the ESP-12e. I'm still going to use the term ESP8266 for all the members of the family.</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzNHYYQDoaLc1wJYVyRsFcWR_y46D6S5ohaRle3xPQaHVFe-kQRsdvgrCwDm6PasgJhI1adAyv_VmlboVtKhB8QCRER5K-5uqbWyQISBzm934EjESuLGktORdgIlkqm3Ae-0auziDFxL23/s1600/ESP-12.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzNHYYQDoaLc1wJYVyRsFcWR_y46D6S5ohaRle3xPQaHVFe-kQRsdvgrCwDm6PasgJhI1adAyv_VmlboVtKhB8QCRER5K-5uqbWyQISBzm934EjESuLGktORdgIlkqm3Ae-0auziDFxL23/s120/ESP-12.jpg" width="120" height="120" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>ESP-12e</a></div></div>
<h3>What's the Big Deal With the ESP8266</h3>
<div style="margin-bottom: 0.1in;">Besides the price, this little device can act as a TCP/IP or UDP server or client. It can connect to your WiFi router, and, as a server, contains its own access point. It's often called the "Internet of Things" device.</div>
<div style="margin-bottom: 0.1in;">I have used it as a client where the server is a Raspberry Pi. I employed two in a remote control project, one as a client, the other a server. I utilized the access point in the server device so it does not need my my WiFi router. The access point has an SSID and a password you choose. </div>
<div style="margin-bottom: 0.1in;"> If you do a search on the ESP8266, and search YouTube videos, most often you find projects involving the internet. And, indeed, my weather project uses the ESP8266 as a client to get the weather from weatherunderground.com. Other common projects fall into the "internet of Things" category. I have not explored this, myself.</div>
<div style="margin-bottom: 0.1in;">"Internet of Things" projects use the ESP8266 as a server. It's connected to some device you wish to control - your front door electronic lock, for example. You call up the ESP8266's IP address on your browser from anywhere in the world. Let's say you wrote a little javascript in your ESP8266's program to create "Lock" and "Unlock" buttons. These appear in your browser window. Push a button and control your lock. Next project, perhaps (though not control my front door lock).</div>
<div style="margin-bottom: 0.1in;">One of the best things about the ESP8266 is how you program it. There are several options including issuing AP commands and using the Lua interpretive language. I'm not going to discuss those but will talk about what I use - writing C code within the Arduino IDE. I've been using the Ardino IDE for quite some time, writing Arduino sketches. My LED display uses the same microcontroller as used on the Arduino Uno, and I use the Arduino IDE to write all the firmware to control the display. </div>
<div style="margin-bottom: 0.1in;">Two wonderful things happened. The Arduino IDE was opened up to other devices, and the people at NodeMCU provided the functionality for writing ESP8266 firmware using the Arduino IDE. I now had one platform for writing code to both the ATmega328P and my ESP8266. Many of the same libraries as used for Arduino devices were adapted for use on the ESP8266. NodeMCU adapted the existing Arduino WiFi shield library to become the ESP8266WiFi library. </div>
<h3>Putting the ESP8266 together With My Display</h3>
<div style="margin-bottom: 0.1in;">Here is my interface board that connects to the rear of my display</div>
<div style="margin-bottom: 0.1in;"><iframe src="https://drive.google.com/file/d/0B8bfN-QZGBgyS1llSGI3R3FlYlU/preview" width="600" height="520"></iframe></div>
<div style="margin-bottom: 0.1in;">Above is the layout of the breadboard PCB that controls my display - my interface board. Until recently, there was nothing to the right of the serial EEPROM. The ESP8266 came later. My ESP8266, the ESP-12e version, exists on a development module designed by NodeMCU. It's $8.79 USD from Amazon. Bit more expensive but adds an USB to serial chip for programming, a voltage regulator (5V to 3.3V) and fits nicely on the breadboard PCB having pins on a 0.1" pitch. It's worth every penny. The TXB0104, between the serial EEPROM and the ESP8266 translateS voltage levels of two signals between the ATmega328P, operating at 5V, and the ESP8266, operating at 3.3V. </div>
<div style="margin-bottom: 0.1in;">I'm not going to go into a lot of detail here. The readme file on GitHub explains a lot, and the sketches have lots of comments. I will say that the ESP8266 connects to the weatherunderground api every 10 minutes. It retrieves two .JSON files - one with the current weather conditions and the other, eight forecasts. It signals the ATmega328P via an interrupt that new data is ready. In the meantime, the ATmega328P is reading the weather data from the serial EEPROM and writing it to the display. I functionally divided the serial EEPROM's 64K memory into 2 kbyte blocks. The first 28 of these blocks are for static messages I write that I wish to display. The weather data sits in the next 2 kbyte space. Once the ATmega328P has written all the weather data to the display, it looks to see if the ESP8266 has sent the interrupt. If, not, it simply repeats the same weather information. If the interrupt occurred, the ARmega328P and the ESP8266 talk to each other using a pseudo SPI handshaking scheme that sends the new data to the ATmega328P. The data in the .JSON file is parsed for the desired information, and along with other text, is written to the serial EEPROM.</div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>
Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-78103348854253907912016-04-22T14:34:00.000-04:002016-04-24T16:55:11.185-04:00Arduino Uno Register Programming and Pulse Width Modulation - Continuous Servo<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<h3>Introduction</h3>
<div style="margin-bottom: 0.1in;">This is a continuation of my last post. I have been discussing the virtues of what I call Arduino "Register Programming". This is all about using the Arduino IDE to program the ATmega328p"s internal registers directly. This is my forth post in the series. The last post, of which this is a continuation, talked about using the ATmega328P's internal timer/counters to control a small DC servo. The servo is a good example because it requires pulse width modulation to do anything and the timer/counters are ideal for that application. That last post got pretty long, thus this continuation.</div>
<h3>The Continuous Servo</h3>
<div style="margin-bottom: 0.1in;">In my last post, I used the noncontinuous servo as an example. The output shaft of this servo only rotates when a change of shaft position is called for. When the new position is reached, the servo stops and holds that position. You can envision this servo controlling the steering of a model car. Only when the steering wheel is moved will the wheels of the car change the direction of travel.</div>
<div style="margin-bottom: 0.1in;">The output shaft of the continuous servo, on the other hand, continues to rotate even if the control signal is constant. Changing the control signal changes the speed and direction of the shaft. An application could be a winch where you can control how fast it turns and whether the cable plays out or pulls in.</div>
<div style="margin-bottom: 0.2in;">I put together a little video that further explains the differences between the two devices and how to program them. The video's Arduino sketch (the same for both types of servos) is very short. The comments, the same as in the sketch in my last post, take up most of the sketch. </div>
<div style="margin-bottom: 0.2in;"><iframe width="560" height="315" src="https://www.youtube.com/embed/pxBXL8c1iDM" frameborder="0" allowfullscreen></iframe></div>
<div style="margin-bottom: 0.1in;">I had a thought while playing with the continuous servo. I wondered how fast the shaft was turning particularly when I tried to balance the speed between CW and CCW rotation with the screw driver. I could only go by the sound it was making to judge speed. The same timer/counter circuit could be used to create a timing light type of tachometer. The flashing rate of a bright LED is controlled by a potentiometer. You illuminate the rotating device by the LED and rotate the potentiometer until the motion of the rotating device appears to stop. In this application, the configuration of the timer/counter will be opposite as used by the servo. The pulse width remains constant while the pulse repetition changes. The potentiometer connects to an A>D converter input of the ATmega328P and the digital output of the A>D is used to program the pulse repetition frequency. A digital display rounds out the equipment controlled by an ATmega328P microcontroller. An interesting, future project. </div>
<div style="margin-bottom: 0.1in;">Here is a timing diagram like the one in the last post but this is actually to scale<b>:</b></div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7IEHNnEbHNfrek2QT4IRmCBtSTgru3w7KqouV7utfV69B-okQGZ1e9XQ8Lfv48k0UHCgvMho4qJFQQdT6IWC6M12WgFdAQSb4abGoBvoZVyDOqTYiBko0H4ZBzT1WsHGbwkXOz2_h3ali/s1600/Rotation+of+IMG_20160424_0001.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7IEHNnEbHNfrek2QT4IRmCBtSTgru3w7KqouV7utfV69B-okQGZ1e9XQ8Lfv48k0UHCgvMho4qJFQQdT6IWC6M12WgFdAQSb4abGoBvoZVyDOqTYiBko0H4ZBzT1WsHGbwkXOz2_h3ali/s590/Rotation+of+IMG_20160424_0001.jpg" /></a></div></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-14093816579548546412016-04-17T14:48:00.000-04:002016-04-17T15:04:21.878-04:00Arduino Uno Register Programming and Pulse Width Modulation<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<h3>Introduction</h3>
<div style="margin-bottom: 0.1in;">My last two posts concerned, what I call, Register Programming of the ATmega328P microcontroller of the Arduino Uno. My last post discussed the expanded capability of interrupts, over and above the functions in the Arduino IDE's reference language. This post concerns the use of the ATmeta328P's counter/timers to manage pulse width modulation (PWM). Pulse width modulation is used to control such things as the light intensity of LEDs and the speed of small DC motors when the intensity or speed is to be changed during operation. If the light intensity or the motor speed is to be constant, supplying the device with a constant DC voltage is sufficient. Some devices such as servos, require PWM just to operate. The repetition rate of the pulses, or PWM frequency is normally kept constant. The variation in light intensity or speed is achieved by varying the width of the pulses (changing the duty cycle). PWM controls these devices by rapidly turning then on and off.</div>
<div style="margin-bottom: 0.1in;">While it is certainly possible to use the Arduino IDE's analogWrite() function, to control LED brightness and motor speed, forget about controlling a servo by this method. The servo requires pulses of a specific frequency. The function analogWrite() produces a fixed PWM frequency of 490Hz or 980Hz depending upon which arduino pin used. Servos I am familiar with requires 50Hz - a big, big difference. </div>
<div style="margin-bottom: 0.1in;">Knowing how to use the ATmega's counter/timers, and how to program the various, associated, registers will give you much better control in any project. </div>
<h3>How I Am Going To Cover The ATmega328P's Timer/Counters</h3>
<div style="margin-bottom: 0.1in;">Atmel equipped the ATmega328P (and the other microcontrollers in the family) with a very robust set of capabilities for it's timer/counters. There are three independent, different, timer/counters. Each timer/counter has many modes, and many options. Rather than trying to cope with all of these variants, now, I am going to present how PWM is created in very general terms. Then, I will include enough of the details to demonstrate controlling a servo. Finally, I will discuss all of those modes and options. </div>
<div style="margin-bottom: 0.1in;">You should certainly download the datasheet for the device. There are four chapter associated with timer/counters. <a href="http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf">Here is a link to the datasheet.</a> I'm going to use the language of the datasheet as much as possible.</div>
<h3>Determining the Repetition Rate of the Pulses (PWD Frequency)</h3>
<div style="margin-bottom: 0.1in;">We know we are going to create a string of pulses of a particular frequency. What in the Arduino already has a repetitive characteristic? How about the 16MHz clock that drives the ATmega328P? That clock will work but may be a little fast and is invariant. The timer/counters use that clock, but we usually feed that clock into divider circuits to produce lower clocks frequencies. There are five or six outputs from these dividers, called prescallers, in the Atmega documentation. Each precaller divides the 16MHz clock by a different power of 2. The prescallers may slow the clock down sufficiently to be useful, but they only give a choice of five or six different PWM frequencies. What if we want something different? Something like 50Hz is impossible from any prescaller, alone. That is where the timer/counters come in to play. </div>
<div style="margin-bottom: 0.1in;">The timer/counter takes the output of the chosen prescaller and further divides the frequency. This divider is not limited to a power of two. It can divide by any whole number from 1 to a maximum number which is determined by the number of bits in the physical counter within the ATmega328P, or by a programmed value. </div>
<div style="margin-bottom: 0.1in;">The timer/counter simply counts the clock pulses it receives from the prescaller. With each clock pulse, the counter increments by one. When it reaches it maximum value, or the number programmed into an associated register, it will count down with the next clock, decrementing by one until it reaches 0. The next clock pulse starts the counter incrementing again. </div>
<div style="margin-bottom: 0.1in;">If we plot the count against time, we get what is commonly called a triangle waveform. The significance of this waveform is that its frequency will correspond to the pulse repetition frequency. It is obvious that this frequency depends upon three factors<b>:</b> the Arduino's 16MHz clock frequency, the prescaller selected, and the count we choose for our timer/counter. Later, we will put all of that together and generate a formula.</div>
<h3>Determining the Pulse Width (Duty Cycle) and Generating the Pulses</h3>
<div style="margin-bottom: 0.1in;">Now that we know how to determine the pulse frequency, let's move on and determine the pulse width and generate the pulses themselves. This is really one operation. We introduce two more elements<b>:</b> a comparator circuit, and the comparator register. For our present discussion, we are going to say that the comparator is part of the circuit that drives one of the Arduino's I/O pins. </div>
<div style="margin-bottom: 0.1in;">The comparator compares two values<b>:</b> the value programmed into the comparator register, and the current value in the timer/counter. Here is were we make our pulses<b>:</b> When the comparator detects that the two values are equal, it changes the logic level of the I/O pin.
Let's assume that the current logic level of the I/O pin is high, and that the timer/counter is at 0. The timer/counter counts up and when it reaches the value programmed into the comparator register the comparator will flip the I/O pin low. The counter/timer continues to count up until it reaches the maximum count we have selected. The counter now counts down and when it, again, reaches the value programmed into the comparator register, the comparator flips the I/O pin High. We now continue to count down to zero, which is where we started. This cycle continues for as long as we let it. To produce pulses, the value of the comparator register must be lower than the value programmed into the timer/counter's register. If the comparator register has a value equal or higher than the timer/counter register, or has a value of 0, the I/O pin's logic level will not change. Here is a diagram of the operation<b>:</b> </div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoa1hOjUqp5TsYKrVl-5RqyHaMEZ3nuwb0Ika-X6RfC0J-tssjVJ2xrgUvvSupQyXwCWN28ws0W-JSfqF7_0rtL33uVAro6XsLyCxXSW2bsPdcsLHtSUsNdnXWOlzrQH8Q9H32vuNyHQWV/s1600/PulseWidthModulation.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoa1hOjUqp5TsYKrVl-5RqyHaMEZ3nuwb0Ika-X6RfC0J-tssjVJ2xrgUvvSupQyXwCWN28ws0W-JSfqF7_0rtL33uVAro6XsLyCxXSW2bsPdcsLHtSUsNdnXWOlzrQH8Q9H32vuNyHQWV/s580/PulseWidthModulation.JPG" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>Pulse Width Modulation - Forming Pulses From Timer/counter and Compare Registers</a></div></div>
<div style="margin-bottom: 0.1in;">It should be obvious that if we lower the line labeled "Pulse Width" (corresponds to the value programmed into the comparator register), the positive portion of the pulses get narrower, while the negative portion gets wider, thus lowering the duty cycle. The frequency will not change. Note that the center of the positive pulse is centered on the peak of the triangle wave. The center of the low pulse is centered upon the count of zero. This has some significance as we will see later when we discuss other modes of operation. </div>
<h3>What's a Servo</h3>
<div style="margin-bottom: 0.1in;">A servo is a device used by radio control models (planes, cars, boats), in robotics, and in other applications where something has to be moved. Something, like the wheels that steer a car, the ailerons of a plane, or the fingers of a robotic hand. </div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; float:left; margin-right:1em; text-align: center;"><a href="https://learn.adafruit.com/system/assets/assets/000/009/656/medium640/beaglebone_motor_servo.jpg?1396894807" > <img height = "120" src="https://learn.adafruit.com/system/assets/assets/000/009/656/medium640/beaglebone_motor_servo.jpg?1396894807" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>Standard Size Servo</a></div></div>
<div style="margin-bottom: 0.1in;">There are industrial servos, usually run by AC. I'm not talking about those (I don't know anything about them). I'm only considering the dc types like in the picture. The photo shows a "standard" size servo. There are smaller ones available. Check out Adafruit and Sparkfun. Also, there are two types<b>:</b> continuous and non-continuous. The following discussion, and my code example, is for the non-continuous servo. I'll discuss the continuous servo in another post.</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; float:right; margin-left:1em; text-align: center;"><a href="https://www.servocity.com/assets/images/Servo_Breakdown.jpg" ><img height = "180" src="https://www.servocity.com/assets/images/Servo_Breakdown.jpg" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>Inside a Non-continuous Servo</a></div></div>
<div style="margin-bottom: 0.1in;">The non-continuous servo rotates through a 180° arc. It consists of a motor connected to a potentiometer (a variable resistor) via a series of gears. The potentiometer shaft also serves as the output shaft that drives your device. When the motor changes the potentiometer setting, it changes a voltage that is fed into a feedback circuit. There is a second voltage feeding the feedback circuit, a voltage derived from pulses from an external device like the PWM output of your Arduino Uno. </div>
<div style="margin-bottom: 0.1in;">The motor rotates until the voltage out of the potentiometer equals the second voltage. When that that happens, the motor stops. The width of the input pulses determine the position of the output shaft. Saying it another way, the motor turns only when the pulse width changes, making the two voltages unequal. When the voltages become equal, again, due to the turning of the potentiometer, the motor stops. The gears greatly reduce the rotational speed of the motor. The torque at the output shaft is increased in the same proportion as the speed is decreased. The beauty of this device, is the motor can turn, and hold fast, against a good deal of applied torque. </div>
<h3>Controlling a Servo</h3>
<div style="margin-bottom: 0.1in;">I have a non-continuous servo I experiment with. I previously discussed this in my post<b>:</b> <a href="http://thepiandi.blogspot.com/2014/03/gertboard-pulse-width-modulation-servo.html">Gertboard - Pulsewidth Modulation - Servo Control</a>. The Gertboard is an attachment for the Raspberry Pi. </div>
<div style="margin-bottom: 0.1in;">The servo has three connections<b>:</b> ground, power, and control. Ground and power connect to an external voltage source. I used 6V worth of AA batteries. Ground and control connect to the Arduino Uno. I used Uno pin 10 for the control signal. </div>
<div style="margin-bottom: 0.1in;">The control signal is a string of pulses of 50Hz - a pulse every 20ms. The servo will be at -90° if the pulse width is 0.5ms, at +90° if the pulse width is 2.5ms. and at zero, if the pulse width is 1.5ms. My understanding is there is some variability in the specifications for different servos. The pulse repetition frequency of 50Hz. seems to be standard, as is the pulse width of the zero position (1.5ms.). It's the maximum and minimum pulse width, at the extreme clockwise and counterclockwise positions, that may vary with the device. Some trial and error may be required. I would start at 1.0ms. and 2.0ms. and see how far your device turns. </div>
<h3>Timer/counter, and the Output and Input Registers</h3>
<div style="margin-bottom: 0.1in;">Now we get play with the ATmega328P's timer/counters within the ATmega328P, There are three of these<b>:</b> Timer/counter0, Timer/counter1, and Timer/counter2. I use Timer/counter1. The registers in Timer/counter1, and in the timer/counter itself, are 16 bits long. We need the 16 bit resolution - Timer/counter0 and Timer/counter2 use 8 bit timer/counters and registers. </div>
<div style="margin-bottom: 0.1in;">Hopefully, you can match the following detailed discussion with the non-specific discussion at the beginning of this post. As I said before, there are a lot of options available. To wit, Timer/counter1 has 15 modes of operation, 12 of which are for pulse width modulation. Table 16-4 of the datasheet lists these modes. We will be using mode 9, "PWM, Phase and Frequency Correct". I'll explain what that means later, when discussing the other modes. Remember, from before, we need to program a register to contain the value of the highest timer/counter count to establish the pulse repetition rate. In the parlance of the datasheet, this value is called "TOP". There is a formula below that comes from the datasheet. That formula uses "max value" to describe the same thing. We also will need a register to determine the width of the pulses. </div>
<div style="margin-bottom: 0.1in;">Now would be an excellent time to look at the block diagram in Fig. 16-1 of the datasheet. You can replace all of the small "n"s, like in "TCNTn" with a "1", because this is Timer/counter1. "TCNTn" becomes "TCNT1", ect. </div>
<div style="margin-bottom: 0.1in;">On the left of the diagram, you see the timer/counter itself: "TCNT1". Below "TCNT1" are two output control registers, "OCR1A" and "OCR1B", and one input control register, "ICR1". The output control registers connect, to "other circuitry" discussed in the next paragraph. I'll discuss "ICR1" pin functionality later. </div>
<div style="margin-bottom: 0.1in;">Let's talk about that "other circuitry". The mode we select controls the interconnections between the various blocks in the block diagram. The output control registers each connect to comparators, depicted as rectangles with equal signs inside. These two comparators also connect to the timer/counter. When the value of the timer/counter equals the value stored in an output control register, a signal is sent to perform some action. In my project, when the comparator between the timer/counter and output control register "OCR1A" reach the same value, the "equal" signal will migrate to the "Control Logic" block (connection set by the mode selection). The result will be that the timer/counter will count down at the next clock from the prescaler. "OCR1A" is programmed with the highest value we want the timer/counter to reach "(TOP", or max value), and, obviously, is used to control the pulse repetition frequency. When the timer/counter reaches zero, called "BOTTOM" in the datasheet, it will count up at the next clock. </div>
<div style="margin-bottom: 0.1in;">The output of the comparator between the timer/counter and output control register "OCR1B" connects to the block called "Waveform Generation". The "Waveform Generation" block connects to the ATmega328P pin "OC1B" (via a programming selection). When the output of this comparator signals equality, "Waveform Generation" circuitry will change the logic state of the pin. Whether it changes from "Low" to "High" or "High" to "Low" depends on whether the timer/counter was counting up or down at the time. It also depends on how we program one of the control registers not shown on the diagram. </div>
<h3>Programming the Registers</h3>
<div style="margin-bottom: 0.1in;">Now is the time to discuss how we determine the value of max count to program into "OCR1A". There is a formula in the datasheet<b>:</b></div>
<div style="margin-bottom: 0.0in;"><b>pulse repetition freq = clock speed / (2 * prescaler * max count)</b></div>
<div style="margin-bottom: 0.0n;">Substituting the known values<b>:</b></div>
<div style="margin-bottom: 0.0in;"><b>50 = 16,000,000 / (2 * prescaler * max count)</b></div>
<div style="margin-bottom: 0.0in;">Rearranging and simplifying<b>:</b></div>
<div style="margin-bottom: 0.1in;"><b>max count = 160,000 / prescaler</b></div>
<div style="margin-bottom: 0.1in;">We have a choice of fixed values for prescaler<b>:</b> 1, 8, 64, 256, and 1024. We want to choose the lowest value of the prescaler to give us the highest value of max count. The larger max count, the greater resolution we will have when programming the pulse width. We can't use the prescaler of 1 because that would give us a max count of 160,000. A 16 bit counter can only count up to 2<sup>16</sup> -1, or 65536. Choosing the next prescaler value, 8, gives us a max count of 20,000. This will do nicely. There is also the happy coincidence that 20,000 is exactly the time between pulses in microseconds. Therefore, when we go to programming the pulse width, of say, 1.5ms., it will be attained by programming a value of 1500. </div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<h3>Generating The Code</h3>
<div style="margin-bottom: 0.1in;">I have a sample sketch below. All it does is slew the servo in 10° steps from +90° to -90° and back again. It runs continuously with 500ms. between steps. Registers "OCR1A" and "OCR1B" can be written to, directly, as can be seen in the sketch. "OCR1A", once set to 20,000 will not change - because the pulse repetition frequency will not change. "OCR1B" changes every time we wish to change the pulse width. </div>
<div style="margin-bottom: 0.1in;">We have four more programming steps to attend to<b>:</b> Selecting the timer/counter mode 9, setting the prescaler to 8, selecting how we want the output pin to change logic state, and making the output pin, "OCP1B", an output. The first three of these will be done by programming two ATmega328P control registers, "TCCR1A" and "TCCR1B"</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNGaT6WksKP46MfzvohODZTEDPMx73oI9TTI8pJwDfyk9Kmv_TJ76TFZBJXxDvZgcNMANOgGNi7pwEnGLZc02cOPXk3Fx7OSvpW6kHrF8ITpT0oRTYzdHtGi_3owwqu2VrMGCsMd6i05TS/s1600/TCCR1A+and+TCCR1B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNGaT6WksKP46MfzvohODZTEDPMx73oI9TTI8pJwDfyk9Kmv_TJ76TFZBJXxDvZgcNMANOgGNi7pwEnGLZc02cOPXk3Fx7OSvpW6kHrF8ITpT0oRTYzdHtGi_3owwqu2VrMGCsMd6i05TS/s550/TCCR1A+and+TCCR1B.jpg" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>Timer/counter1 Control Registers</a></div></div>
<div style="margin-bottom: 0.1in;">When I wrote the code below I included lots of comments that describe the programming of the control registers. No sense of being redundant so have a look at the code. Please look at tables 16-3. 16-4, and 16-5 of the datasheet for further details of the programming of these two control registers.</div>
<script src="https://gist.github.com/RaspPiGuy/32e45ea880c7d5f8d1a5a00b12bb43a1.js"></script>
<div style="margin-bottom: 0.1in;">There is a lot more to discuss, including<b>:</b></div>
<ol>
<li>The other PWM modes
<li>Non-PWM modes
<li>Input control register
<li>Waveform generator modes
<li>Timer/counter0 and Timer.counter2
<li>The continuous servo
<li>Generating and using timer/counter interrupts
<li>Some other uses for the timer/counters
</ol>
<div style="margin-bottom: 0.1in;">I'm going to deal with these issues in my next post or posts.</div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-31570192317634884322016-03-11T14:26:00.001-05:002016-03-16T09:26:29.842-04:00Interrupts and the Arduino Uno<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<h3>Introduction</h3>
<div style="margin-bottom: 0.1in;">This post is a logical follow-up on my last post: <a href="http://thepiandi.blogspot.com/2016/01/programming-atmega328p-registers-from.html">"Programming the ATmega328P Registers From the Arduino IDE"</a>. This discussion is about using the Uno's interrupts. You have two ways to monitor the Uno's I/O pins (to monitor switches, for example). You can poll for inputs to change state, or you can use interrupts to sense when a change of state occurs.</div>
<div style="margin-bottom: 0.1in;">Polling means you are just going to check the state of Uno I/O pins. In a simple system this if fine. Polling means your sketch does nothing else while you check the state of pins. Interrupts are a way to check pins without your sketch diverting its attention from its main tasks. </div>
<div style="margin-bottom: 0.1in;">Here is an example taken from a project I have been reporting on in this blog<b>:</b> I have an enclosure that accepts a large number of temperature sensors. Measurements are made and the results are transmitted to a Raspberry Pi for storage and graphing. The enclosure has a 2 line by 16 character display. I use the first line to display a sensor's description, and the second line to display the sensor's latest temperature measurement. Since the display can only show one sensor at a time, I installed a switch that allows me to switch the display between sensors.</div>
<div style="margin-bottom: 0.1in;">I first handled the switch by polling. I included a small routine in my code in a convenient location. This routine looks at the logic level of the pin connected to the switch, and if low, causes the display to go to the next sensor. A lot goes on in my main code, so the routine to check the switch repeats after several seconds have passed. If I'm not pressing the switch when the routine looks, the routine misses the change of state.</div>
<div style="margin-bottom: 0.1in;">The operation just felt awkward. I now monitor the switch by interrupt. Whenever the switch is pressed, an interrupt occurs so my routine in the loop just looks to see if an interrupt occurred, not if my finger is on the switch. Much better operation. </div>
<div style="margin-bottom: 0.1in;">When the condition for an interrupt occurs, a small function, you write, will run immediately. When that function has done all it needs to do, operation is returned to the task your sketch was doing at the time before the interrupt. Since you don't know when the interrupt will occur, you have to look closely at your sketch to assure there are no instances when an interrupt will impact some critical timing. There are ways to handle that situation. Interrupts can be turned on and off at any place in your sketch. </div>
<h3>Interrupts and the Uno</h3>
<div style="margin-bottom: 0.1in;">If you want to use the Uno's interrupts, the Arduino Language Reference states there are only two pins, pin 2 and pin 3 you can use. I'm here to tell you it is possible to generate an interrupt from <b>every</b> I/O pin on the Uno. Unless you are using pins 2 and/or 3, however, you will not be able to use the Arduino IDE functions attachInterrupt() and detachInterrupt(). You can, however, use Register Programming to program interrupts on <b>any</b> I/O pin.</div>
<div style="margin-bottom: 0.1in;">The interrupt capabilities of pins 2 and 3 are, however, more robust. All of the external interrupts, when enabled, will trigger an interrupt whenever a change of logic level is detected. Pins 2 and 3 have three additional capabilities. </div>
<div>The four capabilities available for pins 2 and 3:</div>
<ol>
<li>trigger an interrupt whenever the logic level of the pin changes (high to low or low to high).
<li>only trigger an interrupt whenever the logic level changes from a low to a high.
<li>only trigger an interrupt whenever the logic level changes from a high to a low.
<li>trigger an interrupt whenever the logic level of the pin is low.
</ol>
<div style="margin-bottom: 0.1in;">Every pin operates with choice 1. Only pins 2 and 3 have the additional three choices. </div>
<div style="margin-bottom: 0.1in;">If you are designing a new project, and you know you are going to use interrupts to monitor sensors or switches, certainly plan to use pins 2 and 3. If you need to utilize interrupts from other pins, or would like to learn the advantages of register programming interrupts, read on. </div>
<h3>A Little Review</h3>
<div style="margin-bottom: 0.1in;">From my last post, we will need knowledge of the ATmega328P's datasheet, the AVR library for the ATmega328P, and how we handle pin names. To use register programming, we shift our focus from the Arduino Uno to the ATmega328P, itself. Indeed, you can remove a programmed ATmega328P from your Arduino and use it on a circuit board of your own design. With an FTDI adaptor, you can program the ATmega328P while it is on your circuit board.</div>
<div style="margin-bottom: 0.1in;">To use register programming, we will not be using the pin numbers printed on the Uno (like pins 2 and 3). We will use the pin nomenclature found on the ATmega328P microcontroller datasheet. I'm going to repeat a graphic from my last post. Its a partial schematic showing how the Uno's pins connect to the ATmega328P:</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKWY80rESEk3CPq1xqxQbDoKk-npSdJP9GGKo6ADuLpcXS84T1APslYh-iC3lI3MPIDvQyaADtNPyBd9ZeMx0qHBf535-kxOuq0tXdoMNJ15vw4Ia0izPPrLwaA2bLWk7dMR0lkfmnd6J_/s1600/ATmega2Arduino.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKWY80rESEk3CPq1xqxQbDoKk-npSdJP9GGKo6ADuLpcXS84T1APslYh-iC3lI3MPIDvQyaADtNPyBd9ZeMx0qHBf535-kxOuq0tXdoMNJ15vw4Ia0izPPrLwaA2bLWk7dMR0lkfmnd6J_/s600/ATmega2Arduino.png" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>ATmega328P and Arduino Uno I/O Pins</a></div></div>
<div>All of the ATmega328P pins that connect to the Uno I/O pins have multiple functions. For example, the ATmega328P pin 2 has this label inside the graphic for the chip: "PD0 PCINT16/RXD". That means this pin has three functions:</div>
<ol>
<li>PD0 - Standard I/O function, Port D, Pin 0
<li>PCINT16 - External Interrupt Number 16. One of 24 External Interrupts. ATmega documentation calls them Pin Change Interrupts
<li>RXD - UART Receive Pin. For Serial Input From External Devices
</ol>
<h3>External Interrupt Register Programming - Register Definitions From the ATmega328P DataSheet</h3>
<div style="margin-bottom: 0.1in;">I cobbled together the following from the ATmega328P datasheet<b>:</b> </div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_4wbBnuou4QtpGZywdUZv6jtEVVcjfkUC6nlOoxQWaXmPHdsBBkCMvHfJ2H1THPBumYPFFDuQtv5ouU1EtZYSm24PkNRdaTc4V4ty22H6F6ubNY0pSZ6auL9FLdNj6aeyEqnJUv0kC5H-/s1600/Interrupt+Registers+Of+The+ATmega328P.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_4wbBnuou4QtpGZywdUZv6jtEVVcjfkUC6nlOoxQWaXmPHdsBBkCMvHfJ2H1THPBumYPFFDuQtv5ouU1EtZYSm24PkNRdaTc4V4ty22H6F6ubNY0pSZ6auL9FLdNj6aeyEqnJUv0kC5H-/s580/Interrupt+Registers+Of+The+ATmega328P.jpg" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>ATmega328P External Interrupt Registers</a></div></div>
<div style="margin-bottom: 0.1in;"><b>Pin Change Interrupt Control Register, PCICR:</b> As I described in my last post, the ATmega328P has three ports, Port B, Port C, and Port D. PCICR lets you to enable or disable interrupts on any of the three ports. You can enable interrupts on more than one port. To enable interrupts on a specific port, write a "1" to the applicable bit in the PCICR register. Writing a "0" disables interrupts on the applicable port. Use the following when writing to PCICR:</div>
<ul>
<li><b>PCIEO</b> (bit 0) controls the interrupts on Port B, pins PCINT0 - PCINT7. PCINT6 and PCINT7 are not available as those pins connect to the crystal.
<li><b>PCIE1</b> (bit 1) controls the interrupts on Port C, pins PCINT8 - PCINT14. PCINT14 is not available as it reserved for the RESET function.
<li><b>PCIE2</b> (bit 2) controls the interrupts on Port D, pins PCINT15 - PCINT23.
</ul>
<div style="margin-bottom: 0.1in;"><b>Pin Change Mask Registers, PCMSK0, PCMSK1, PCMSK2:</b> These three registers let you enable or disable individual pins in a port whose interrupts have been enabled with the PCICR register.</div>
<h3>External Interrupt Register Programming - The ATmega328P Arduino Library</h3>
<div style="margin-bottom: 0.1in;">As mentioned in the last post, you do not have to consult the library. I include it to show how the datasheet, pin names, and the library come together to help you to write your sketches. The "#defines" in the library show what names you can use in your sketches. These names relate directly to the names in the datasheet register definitions and the ATmega328P pin names, as shown in the datasheet.</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr_q9UbwNCbxGngc2BcZLOegzL27qWS7mmJplLGoNs23WzSvX5BtypaQNyNjzuEjve-7f_QROvRN87ThVUaITP2ZDwhwdHvzN5sO9dEhH61zglmrWugEE0IHWXiu28Bm-jAMtNHlfMxdg3/s1600/Interrupt+-+Library1+.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr_q9UbwNCbxGngc2BcZLOegzL27qWS7mmJplLGoNs23WzSvX5BtypaQNyNjzuEjve-7f_QROvRN87ThVUaITP2ZDwhwdHvzN5sO9dEhH61zglmrWugEE0IHWXiu28Bm-jAMtNHlfMxdg3/s640/Interrupt+-+Library1+.jpg" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>From the iom328p.Library</a></div>
<h3>Examples Using Interrupts</h3>
<div style="margin-bottom: 0.1in;">From my setup in my last post, I'm going to use the red and green switches, and the Arduino Uno. I/m not using the LEDs. If a switch is pressed, a message to the serial monitor will appear. </div>
<div style="margin-bottom: 0.1in;">In my first script, below, I will connect the green switch to PC4 (PCINT12, Uno Pin A4), and the red switch to PC5 (PCINT13, Uno pin A5). In this example, both switches connect to the same port. In setup you can see where I have setup my registers. Remember, from my last post I use the ATmega328p's internal pull-up resistors. They are enabled in line 28. Lines 32 and 33 enable interrupts for the two switches. That should be self-explanatory from the preceding discussion.</div>
<div style="margin-bottom: 0.1in;">Here is where the magic happens<b>:</b> Note lines 13 to 20. This function is called the "Interrupt Service Routine" or ISR. Most of the time we will be in the while loop in setup. If either switch is pressed, processing diverts to the interrupt service routine. When this routine is done, processing goes back to where it was in the while loop.</div>
<div style="margin-bottom: 0.1in;">It is important that you write line 13, the function definition, exactly as shown in my sketch (except for the comment, of course). This ISR will react to any enabled interrupt on port C. If you enabled interrupts on port B, or port D you would substitute "(PCINT0_vect)", or "(PCINT2_vect)", respectively, for "(PCINT1_vect)". </div>
<div style="margin-bottom: 0.1in;">You want your interrupt service routine to be as short as possible. Do not use delay() in the ISR, delay(), itself, uses interrupts. If you use millis() in your code, millis() will not continue to increment while you are in the ISR, resulting in errors. </div>
<div style="margin-bottom: 0.1in;">Any variable declared outside of the ISR, but changed inside the ISR should be declared with the modifier "volatile". This changes where the values of these variables are stored within the ATmega328P. Declaring them as volatile assures the values will be stored in RAM and not in a register - more important is the fact the values will not be lost. In our case that refers to the variasbles "data" and "foundInterrupt". </div>
<div style="margin-bottom: 0.1in;">What does the ISR do? First, it reads PINC (the port C input register), masks out all bits but those related to PC4, and PC5, and stores the value in the variable "data". Second, it disables the port C interrupts - this is a way to debounce the switch (further key presses will not trigger an interrupt). Lastly, it makes the Boolean variable "foundInterrupt" true. When it has done all of these things, it exits back to the while() loop.</div>
<div style="margin-bottom: 0.1in;">Back in the while()n loop, The first "IF" statement will now be true. We now look at the variable "data" to see which switch was pressed (The bit will be low for the switch that was pressed). Variable "foundInterrupt" is set to false and the masked value of PINC is check. If neither switch is pressed, the interrupt for port C is enabled again. This last is another way to effect switch debounding. This assures that only one message will be displayed for each switch press. In this scenario, it is not possible to detect if both switches are pressed at the same time. </div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<script src="https://gist.github.com/RaspPiGuy/20841f092f13f4652bc9.js"></script>
<div style="margin-bottom: 0.1in;">The sketch below illustrates connecting the two switches to different ports. The green switch connects to PB0 (PCINT0, Uno pin 8). The red switch connects to PC5 (PCINT13, Uno pin A5). As with the last sketch, look at setup() to see how the ports, pullup resistors, and interrupts are setup.</div>
<div style="margin-bottom: 0.1in;">Since we would like to detect interrupts on both the B and C ports, we need an interrupt service routine for both ports. The two ISRs are very simple. When a switch is pressed, variable "foundInterrupt_PortB", or "foundInterrupt_PortC", is made true. Also, the interrupt for that port is disabled. This is for switch debounce to avoid multiple interrupts (without this provision, an interrupt would occur whenever the switch is pressed and whenever the switch was released). </div>
<div style="margin-bottom: 0.1in;">I think the code in the while() loop is pretty clear. Note that this sketch allows the possibility to detect both switches pressed. Since the while() loop has a 2 second delay, if both switches are pressed within the same two second period, the serial monitor will show that both are pressed. To avoid that situation, you should disable <b>both</b> interrupts in the two ISRs. The last part of the while() loop enables the two interrupts if both switches are released.</div>
<script src="https://gist.github.com/RaspPiGuy/87531749080756a53c2a.js"></script>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com2tag:blogger.com,1999:blog-7443803799514447902.post-15089332173314520972016-01-07T12:28:00.000-05:002016-03-10T16:53:45.631-05:00Programming the ATmega328P Registers From the Arduino IDE<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<h3>Please Note<b>:</b></h3>
<div style="margin-bottom: 0.1in;">Because I have no experience with other Arduino boards, I'm going to confine my comments to the Arduino Uno and the Atmel ATmega328P microprocessor.</div>
<h3>Introduction</h3>
<div>If you desire to do something beyond the Arduino programming language, like program an interrupt for any Uno I/O pin, do more precise control of pulse width modulation, or write to the EEPROM within the ATmega328P, you need to learn about the ATmega328P's internal registers. If you are studying someone else's code and see something like<b>:</b></div>
<div style="margin-bottom: 0.1in;"> PORTD |= (1 << PORTD1);</div>
<div style="margin-bottom: 0.1in;">and you wondered what that meant, read on. By utilizing what I call "Register Programming", besides the examples above, you can more efficiently program the three I/O ports, use the ATmega328P's internal timers, program it's SPI, I<sup>2</sup>C, and serial interfaces, and make better use of the Analog to Digital converter pins, and the analog comparator. </div>
<div style="margin-bottom: 0.1in;">I would not attempt to control a servo with the AnalogWrite() function. You need more resolution than 1 part in 256. Also, the frequency is wrong. AnalogWrite() gives you a frequency of 490Hz or 980Hz depending on the pin. The very common servo I am familiar with requires a frequency of 50Hz. Register programming gives you the opportunity of using an ATmega328P counter that gives you one part 65536 resolution rather than 256. You can also set the frequency exactly to your needs.</div>
<div style="margin-bottom: 0.1in;">What are these registers? They are eight bit bytes of SRAM memory within the ATmega328P. These registers can be accessed through programming via the Arduino IDE. If you write "digitalWrite(13, HIGH);" in your code, you are writing to one of these resisters. The ATmega328P has 224 of these registers, but most are reserved for future use. I count 86 that are useful. All of these have particular purposes.</div>
<h3>Resources</h3>
<div>To do Register Programming you need three basic resources:</div>
<ol>
<li>Comparison between Arduino I/O pins and ATmega328P pins
<li>ATmega328P datasheet
<li>AVR libraries on your computer
</ol>
<h3>Arduino Pins and the ATmega328P</h3>
<div>The following partial schematic represents the ATmega328P and the Arduino Uno's pins as printed on the device and as used in the language reference<b>:</b></div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKWY80rESEk3CPq1xqxQbDoKk-npSdJP9GGKo6ADuLpcXS84T1APslYh-iC3lI3MPIDvQyaADtNPyBd9ZeMx0qHBf535-kxOuq0tXdoMNJ15vw4Ia0izPPrLwaA2bLWk7dMR0lkfmnd6J_/s1600/ATmega2Arduino.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKWY80rESEk3CPq1xqxQbDoKk-npSdJP9GGKo6ADuLpcXS84T1APslYh-iC3lI3MPIDvQyaADtNPyBd9ZeMx0qHBf535-kxOuq0tXdoMNJ15vw4Ia0izPPrLwaA2bLWk7dMR0lkfmnd6J_/s600/ATmega2Arduino.png" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>ATmega328P and Arduino Uno I/O Pins</a></div></div>
<div style="margin-bottom: 0.1in;">The graphic of ATmega328P looks really messy. That is because, all the I/O pins, except power and grounds, have multiple functions. For the moment, we will concentrate on the ATmega328P's pin nomenclature closest to the border of the graphic, namely PB0 to PB7, PC0 to PC6, and PD0 to PD7. All but three of these pins connect to Arduino Uno I/O pins. PC6 does not because it is used by the Uno as a reset to the ATmega328P. PB6 and PB7 connect to the 16MHz crystal so can not be used as I/O pins. The other pins make up three ports, B, C, and D. Each port is controlled or monitored by three ATmega328P registers.</div>
<h3>ATmega328P Datasheet</h3>
<div style="margin-bottom: 0.1in;">The next resource is the Atmel datasheet for the ATmega family of microcontrollers. <a href="http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf">Here is a link to that document.</a></div>
<div style="margin-bottom: 0.1in;">Every function and every register is clearly presented and explained in the datasheet. You can learn a lot and do a lot by reading this document. Besides the control of the port registers, I have used the timer registers to precisely control motors and servos (better than using the Arduino's analogWrite() function). I have also used the registers for writing to and reading from the ATmega328P's internal EEPROM, and I have used them to utilize external interrupts. </div>
<h3>ATmega328P Port Registers</h3>
<div>Let's create an example using one of the three port registers. We will use all eight pins of port D. Four LEDs will connect to PD0 to PD3. These correspond to pins labeled 0 to 3 on the Uno. We will connect four switches to PD4 to PD7. These correspond to pins labeled 4 to 7 on the Uno. Here is the partial schematic<b>:</b></div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggrCxs3bkrWfr0zgwoxlACsNYy-4tGGSCfsn3c4YDg9AWqy16BCUaC8xrxKedIVv5OmhydxCpff1GnggQQk4TdVIhqdZ4ZKS1ypYWMHiyVhJZ-0z5DMgx3m2r75IHRTk-6YpiLQsFI_z_-/s1600/ATmega2Arduino_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggrCxs3bkrWfr0zgwoxlACsNYy-4tGGSCfsn3c4YDg9AWqy16BCUaC8xrxKedIVv5OmhydxCpff1GnggQQk4TdVIhqdZ4ZKS1ypYWMHiyVhJZ-0z5DMgx3m2r75IHRTk-6YpiLQsFI_z_-/s580/ATmega2Arduino_1.png" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>Connecting LEDs and Switches To the ATmega328P</a></div></div>
<div>The following is copied directly from the datasheet for the ATmega328P. It details the three registers devoted to Port D<b>:</b></div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcPDInzheSmmbm_odbGMfq4_nkbq4AsejPUDs9-cjltMCE_vpdPc-KOV74veXWSZXtnLfW4ORswOa-47VW77m6v48gtxa81qARjF2V6JwVOUT1WDHs_Ao-qGcDHcT34wx1lmbweXCanbut/s1600/PortD-DataSheet.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcPDInzheSmmbm_odbGMfq4_nkbq4AsejPUDs9-cjltMCE_vpdPc-KOV74veXWSZXtnLfW4ORswOa-47VW77m6v48gtxa81qARjF2V6JwVOUT1WDHs_Ao-qGcDHcT34wx1lmbweXCanbut/s580/PortD-DataSheet.jpg" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>From the Data Sheet. The Three Port D Registers</a></div></div>
<h3>AVR Libraries On Your Computer</h3>
<div style="margin-bottom: 0.1in;">Here is the final resource. YOU DO NOT NEED TO CONSULT THESE LIBRARIES TO PROGRAM YOUR DEVICES. I include this discussion to show why the Arduino IDE compiler allows you to use the Atmel register and register bit names in your code. </div>
<div style="margin-bottom: 0.1in;">Atmel has supplied libraries for a large number of their microcontrollers to the Arduino development suite. If you have a PC, more than likely, you will find these libraries here<b>:</b> </div>
<div style="margin-bottom: 0.1in;"> C:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include\avr. </div>
<div style="margin-bottom: 0.1in;">There are 285 library files in this directory. No matter what version of the Arduino you have, you only need to know of one these libraries<b>: io.h</b>. You insert "#include <avr\io.h>" at the top of your code. The Arduino IDE, when compiling, will look at this file and knowing the specific Arduino you are using, will go to the appropriate library file. For the Arduino Uno, that library is <b>iom328p.h</b>. Wish I could print out the entire file here, but it is quite long.</div>
<div style="margin-bottom: 0.1in;">iom328p.h consists of many, many #define statements. There is a #define for each of the ATmega328P's registers, and #define statements for each bit of each register. I never counted them, but I would think all 86 registers are addressed. All the nomenclature in the library is taken directly from the data sheet. PORTD in the data sheet is PORTD in the library. Consequently, you can write "PORTD" in your code. </div>
<div>Here is the portion of the library that deals with the three PORTD registers. Note the text corresponds exactly to the text in the data sheet<b>:</b></div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo4O3Cfuh7HKX1nc4PhztXlMum0a8s1nrDpwADejaR9NFeQPrhWRVkVTOQ1mGsIVylHFRtah4t5QYqxT3-MyqtYS6uliPB9BPJ0yw_4Ac6uScsb8PavWqrarO8jvIknkbIo203bY6VhQGP/s1600/PortD-Library.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo4O3Cfuh7HKX1nc4PhztXlMum0a8s1nrDpwADejaR9NFeQPrhWRVkVTOQ1mGsIVylHFRtah4t5QYqxT3-MyqtYS6uliPB9BPJ0yw_4Ac6uScsb8PavWqrarO8jvIknkbIo203bY6VhQGP/s400/PortD-Library.JPG" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>From the iom328p.h Library</a></div></div>
<h3>Putting It All Together and Writing Code</h3>
<div style="margin-bottom: 0.1in;">While the text in the library conforms to the text in the data sheet register descriptions, the text on the schematic (also taken from the data sheet) does not. For example, the schematic pin labeled PD7 corresponds to PORTD7 in the PORTD register, PIND7 in the PIND register, and DDD7 in the DDRD register.</div>
<div style="margin-bottom: 0.1in;">Now that we know that we can use the register names, like DDRD, and the register individual bit names, like DDD2, how do we write code? There are two basic ways I do it. If I want to specify all eight bits in a register (initializing a register), I will write something like this<b>:</b> </div>
<div> PORTD = 0; //writes 0 to all eight bits.</div>
<div style="margin-bottom: 0.1in;"> PORTD = 0b11110000; //top 4 bits high, lower 4 low.</div>
<div style="margin-bottom: 0.1in;">If, however, I wish to simply change one, or more bits, without effecting the other bits in a register, I will do something like this<b>:</b></div>
<div style="margin-bottom: 0.1in;"> PORTD |= (1 << PORTD2);</div>
<div style="margin-bottom: 0.1in;">This will make the logic level of I/O pin PD2 high, without effecting any of the other seven bits of PORT D. Rather than explain how this works here, I'll let you read further down this post where it will be explained.</div>
<div style="margin-bottom: 0.1in;">Finally, it is time to discuss the functions of the three registers and how to used them in your code. We will make use of those four switches and four LEDs of our example circuit in our discussion.</div>
<h3>The Data Direction Registers - DDRB, DDRC, and DDRD</h3>
<div>The ATmega328P needs to know how you are using its pins. Are they inputs or outputs? That is the purpose of the data direction registers. You write a 1 to make a pin an output and a 0 to make it an input. In our example, PD0 to PD3 will be outputs, while PD4 to PD7 will be inputs. PD0 corresponds to DDD0 in the DDRD register. The other pins follow the same pattern as PD0. We now have enough information to write a line of code to establish which pins are inputs or outputs<b>:</b></div>
<div style="margin-bottom: 0.1in;"> DDRD = 0b00001111;</div>
<div>I'm using the binary representation (0b00001111 rather than 15 in decimal) because I can easily see each of the eight bits of DDRD. This is equivalent to using the pinMode() function in the Arduino language. However, using pinMode() you need to write eight lines of code<b>:</b></div>
<div> pinMode(0, OUTPUT);</div>
<div> pinMode(1, OUTPUT);</div>
<div> pinMode(2, OUTPUT);</div>
<div> pinMode(3, OUTPUT);</div>
<div> pinMode(4, INPUT_PULLUP);</div>
<div> pinMode(5, INPUT_PULLUP);</div>
<div> pinMode(6, INPUT_PULLUP);</div>
<div style="margin-bottom: 0.1in;"> pinMode(7, INPUT_PULLUP);</div>
<h3>Internal Pull-Up Resistors</h3>
<div style="margin-bottom: 0.1in;">What's with the PULLUP notation? As shown in the schematic, without further effort, the switches have no useful function. Whether a switch is pressed, or not, a logic 0 will be seen at the switch's pin. There are two ways to make the switches useful. The first is to connect a resistor between each of a switch's I/O pin and 5V. With this "pull-up" resistor connected, a logic 1 is recorded at the pin if the switch is not pressed. Since the switch connects the I/O pin to ground, a logic 0 will be recorded if the switch is pressed.</div>
<div style="margin-bottom: 0.1in;">The second way utilizes a convenient feature of the ATmega328P. Each I/O pin has an internal pull-up resistor that can be connected at the pin. These ATmega328p pull-up resistors are connected by programming. We have seen how that is done using pinMode(). We can do the same, and do it for all four switches, in one statement using register programming. Per our example, we will use the PORTD register. </div>
<div>If you look in the data sheet at the description of the PORT registers, you will find if a pin is declared an input, in the port's DDR register, programming a 1 in the pin's PORT register will turn on the internal pull-up resistor. To make it clear, in our example, PD4 - PD7 have been declared inputs. Therefore, we will program PORTD4, PORTD5, PORTD6, and PROTD7 as 1s. We will do this in one line of code<b>:</b></div>
<div style="margin-bottom: 0.1in;"> PORTD = 0b11110000;</div>
<h3>Port Registers - PORTB, PORTC, and PORTD</h3>
<div>We have already seen an example of using the port register for enabling the internal pull-up resistors of input pins. The other obvious use of these registers is to turn on and turn off external components like LEDs. In our example, we have four LEDs. In the line of code above, where we connected internal pull-up resistors, we have also turned the four LEDs off. A logic 0 provides, essentially, ground voltage to the device. A logic 1 provides, essentially, +5V to the device. In our case, 0 volts turns the LEDs off. To turn an LED on, program a 1 to the pin's PORTD register. To turn LEDs D1 and D3 on, and to keep LEDs D2 and D4 off, we can write the following line of code<b>:</b></div>
<div style="margin-bottom: 0.1in;"> PORTD = 0b11110101;</div>
<div style="margin-bottom: 0.1in;">Note, by writing the line above, we have to keep track of the logic levels of all eight pins in port D. Sometimes, that is not convenient, and not possible. Once we setup those pull-up resistors, we don't want to inadvertently disconnect them by programming. What we need then is a way to write to as few as one pin in the PORTD register without disturbing the logic levels of the other pins. To do that we need to be familiarize ourselves with the logic functions given to us by mathematician George Boole<b>:</b> the bitwise operators. </div>
<h3>The Bitwise Operators</h3>
<div>What does the following statement do?</div>
<div style="margin-bottom: 0.1in;"> PORTD |= (1 << PORTD1);</div>
<div style="margin-bottom: 0.1in;">This statement will turn on LED D2 without effecting the other seven bits of port D. It utilizes two of the six bitwise operators. Let's list the six operators and the characters that represent them in code<b>:</b></div>
<table style= "width: 50%;">
<tr>
<td><b>~</b></td>
<td>NOT</td>
</tr>
<tr>
<td><b>&</b></td>
<td>AND</td>
</tr>
<tr>
<td><b>|</b></td>
<td>OR</td>
</tr>
<tr>
<td><b>^</b></td>
<td>EXCLUSIVE OR</td>
</tr>
<tr>
<td><b><<</b></td>
<td>SHIFT LEFT</td>
<tr>
<tr>
<td><b>>></b></td>
<td>SHIFT RIGHT</td>
<tr>
</tr></table>
<div style="margin-bottom: 0.1in;">These operators are called bitwise because they operate on individual bits of a byte. </div>
<h3>The NOT Operator ~</h3>
<div style="margin-bottom: 0.1in;">This is the simplest operator. It will flip all eight bits of a byte. The 1s become 0s and the 0s, 1s. For example, if PORTD = 0b00001111, ~PORTD = 0b11110000. </div>
<h3>The AND Operator &</h3>
<div style="margin-bottom: 0.1in;">This takes two bytes and results in a third byte. The best way to visualize the operation is to place one byte over the other and then state the rule. For example<b>:</b>. </div>
<div> 00001111 the first byte</div>
<div>  <u>01000010</u> AND with the second byte</div>
<div style="margin-bottom: 0.1in;"> 00000010 the resulting byte</div>
<div style="margin-bottom: 0.1in;">We compare the two bits, in the same bit position, of each byte, and come up with the value of the bit, in the same bit position, in the resulting byte. The rule for the AND operation<b>:</b> if BOTH bits are a 1, the resulting bit is a 1. If either bit is, or both bits are, a 0, the resulting bit is a 0. </div>
<h3>The OR Operator |</h3>
<div style="margin-bottom: 0.1in;">This also takes two bytes and results in a third byte. For example<b>:</b>. </div>
<div> 00001111 the first byte</div>
<div> <u>01000010</u> OR with the second byte</div>
<div style="margin-bottom: 0.1in;"> 01001111 the resulting byte</div>
<div style="margin-bottom: 0.1in;">The rule for the OR operation<b>:</b> if EITHER bit is a 1, the resulting bit is a 1. If BOTH bits are a 0, the resulting bit is a 0. </div>
<h3>The EXCLUSIVE OR Operator ^</h3>
<div style="margin-bottom: 0.1in;">This takes two bytes and results in a third byte. For example<b>:</b>. </div>
<div> 00001111 the first byte</div>
<div> <u>01000010</u> EXCLUSIVE OR with the second byte</div>
<div style="margin-bottom: 0.1in;"> 01001101 the resulting byte</div>
<div style="margin-bottom: 0.1in;">The rule for the EXCLUSIVE OR operation<b>:</b> if BOTH bits are the SAME, the resulting bit is a 0. If the bits are DIFFERENT, the result is a 1. This also has the useful function of flipping, or not flipping a bit. A logic 1 in a bit position of one byte will flip the corresponding bit in the second byte. A logic 0 in a bit position of one byte will leave the corresponding bit in the second byte unchanged. </div>
<h3>The SHIFT LEFT Operator <<</h3>
<div style="margin-bottom: 0.1in;">This operator takes a byte and an argument. The argument of the operator indicates how may times we will shift all the bits in the byte to the left. After each shift, a 0 is loaded into the least significant bit position (the bit on the right end). If we have the expression "PORTD << 3;", and PORTD is 0b00001111, the resulting byte is 0b01111000. </div>
<h3>The SHIFT RIGHT Operator >></h3>
<div style="margin-bottom: 0.1in;">This operator also takes a byte and an argument. The argument of the operator indicates how may times we will shift all the bits in the byte to the right. After each shift, a 0 is loaded into the most significant bit position (the bit on the left end). If we have the expression "PORTD >> 3;", and PORTD is 0b00001111, the resulting byte is 0b00000001. </div>
<h3>Now That We Have The Fundamentals, Let's Light Some LEDs</h3>
<div>How would we turn on LED D3 and not effect the other LEDs or the switches? Let's write the line of code and then take it apart<b>:</b></div>
<div style="margin-bottom: 0.1in;"> PORTD |= (1 << PORTD2);</div>
<div>First, we know that is a compound operation like "A += 1;" is the same as "A = A + 1;" We can expand our expression to<b>:</b></div>
<div style="margin-bottom: 0.1in;"> PORTD = PORTD | (1 << PORTD2);</div>
<div style="margin-bottom: 0.1in;">Looking at the library we see "#define PORTD2 2". We can replace PORTD2 with 2, as below<b>:</b></div>
<div style="margin-bottom: 0.1in;"> PORTD = PORTD | (1 << 2);</div>
<div style="margin-bottom: 0.1in;">(1 << 2) indicates a shift left with the argument of 2. The operand is the integer 1 which we can state in binary form as 0b0000000000000001. The operation wants us to left shift this twice putting a 0 in the least significant bit position each time. The result of (1 << 2) is 0b0000000000000100. We can drop the upper eight bits as they will have no impact when next operating on the eight bit PORTD. The result now is 0b00000100. </div>
<div>This now resolves to<b>:</b></div>
<div style="margin-bottom: 0.1in;"> PORTD = PORTD | 0b00000100;</div>
<div>Let's assume PORTD is 0b11110000. Here is what the operation looks like<b>:</b></div>
<div> 11110000 the original value of PORTD</div>
<div> <u>00000100</u> OR with the second byte</div>
<div style="margin-bottom: 0.1in;"> 11110100 the resulting value of PORTD. --- LED D3 TURNS ON.</div>
<div>We turned LED D3 on, now let's turn it off (without effecting the other LEDs or switches. Here is the line of code<b>:</b> </div>
<div style="margin-bottom: 0.1in;"> PORTD &= ~(1 << PORTD2);</div>
<div>Some of the line of code is the same as before. (1 << PORT2) resolves to 0b00000100. However notice the NOT operator, ~. This flips all eight bits resulting in 0b11111011. Now we apply the AND operation as shown below<b>:</b></div>
<div> 11110100 the original value of PORTD</div>
<div> <u>11111011</u> AND with the second byte</div>
<div style="margin-bottom: 0.1in;"> 11110000 the resulting value of PORTD. --- LED D3 TURNS OFF.</div>
<h3>Writing To Multiple Outputs</h3>
<div>What if you wanted to turn on (or off) two or more LEDs? You can string the operations together in one line. Let's turn on LED D1 and LED D4, then turn them off<b>:</b></div>
<div> PORTD |= (1 << PORTD0) | (1 << PORTD3); ON </div>
<div style="margin-bottom: 0.1in;"> PORTD &= ~(1 << PORTD0) & ~(1 << PORTD3); OFF </div>
<div>You can even mix them. This will turn LED D1 and LED D3 on and LED D2 and LED D4 off<b>:</b></div>
<div style="margin-bottom: 0.1in;"> PORTD |= (1 << PORTD0) & ~(1 << PORTD1) | (1 << PORTD2) & ~(1 << PORTD3);</div>
<div>For more fun, stick that line above in setup(), and add the following lines in loop()<b>:</b></div>
<div> PORTD ^= (1 << PORTD0) ^ (1 << PORTD1) ^ (1 << PORTD2) ^ (1 << PORTD3);</div>
<div style="margin-bottom: 0.1in;"> delay(500);</div>
<div style="margin-bottom: 0.1in;">This will toggle the four LEDs at a 1Hz cycle. Try it.</div>
<h3>Reading the Logic Level of Input Pins</h3>
<div>We Can't Forget Those Switches. Continuing the example, the switches are connected to input I/O pins. To read a pin that has been declared an input we use one of the PIN registers. In our case, that will be PIND. Since we have four switches we need a way to read one switch and ignore the others. To see how this is done, the line of code to evaluate if switch SW1 (connected to PD4) is pressed is<b>:</b></div>
<div style="margin-bottom: 0.1in;"> PIND &= (1 << PIND4);</div>
<div style="margin-bottom: 0.1in;">The above expression will be logic 0 if SW1 is pressed and not 0, actually 16, if released. The other switches will not effect the result. </div>
<div style="margin-bottom: 0.1in;">I, frankly, don't always use that last method for reading from a register. I usually establish, and apply an eight bit datamask to the value in the PIN register. Like this to read the value of PIND4<b>:</b></div>
<div> byte datamask = 0b00010000;</div>
<div style="margin-bottom: 0.1in;"> byte data;</div>
<div style="margin-bottom: 0.1in;"> data = PIND & datamask;</div>
<div style="margin-bottom: 0.1in;">Here is a simple sketch. If SW1 is pressed, LED D1 will light, etc. This is not the best way to do this as it allows multiple LEDs to be lit and there is no switch debouching. The better way is to use interrupts to signal when a switch is pressed. My next blog entry will deal with that exact topic. Interrupts also are best handled with register programming.</div>
<div style="margin-bottom: 0.1in;"><script src="https://gist.github.com/RaspPiGuy/5b4dcc1111fb7d6a9c6c.js"></script></div>
<h3>One More Thing</h3>
<div style="margin-bottom: 0.1in;">Here is a photo of the actual hardware:</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuIRBNraYm0foA3WFtCD99L6nJRoCz989soGoieQJ0Fu8xS8xDAVrXrc0x3y-YJHRIhRFv6vyI7G6mYMfCZv9qlLIeKJsxIecaO4cSK1Pw0xgdcJC6ZuJ1EIqnXBgki4apLLNLWuiPDP8Y/s1600/LEDsAndSwitches.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuIRBNraYm0foA3WFtCD99L6nJRoCz989soGoieQJ0Fu8xS8xDAVrXrc0x3y-YJHRIhRFv6vyI7G6mYMfCZv9qlLIeKJsxIecaO4cSK1Pw0xgdcJC6ZuJ1EIqnXBgki4apLLNLWuiPDP8Y/s400/LEDsAndSwitches.jpg" /><div class = "caption"><font color = "blue"><i><center></i></center></font color></div>The Hardware</a></div></div>
<div style="margin-bottom: 0.1in;">I had to Photoshop in the colors of the LEDs. They are of clear plastic and do not photograph well when lit. </div>
<div style="margin-bottom: 0.1in;">Since we have introduced color, why not put that into the program. Here is the sketch carried to the extreme by adding a bunch of #define statements<b>:</b> </div>
<div style="margin-bottom: 0.1in;"><script src="https://gist.github.com/RaspPiGuy/30bfba11cfbc8ce284f9.js"></script></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com5tag:blogger.com,1999:blog-7443803799514447902.post-51931203093289026342015-04-20T13:35:00.001-04:002015-04-20T13:53:58.955-04:00Serial Transmission - Gertboard (Like an Arduino) to Raspberry Pi<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<h3>Introduction</h3>
<div style="margin-bottom: 0.1in;">If you read my post of March 14, you know I have an enclosure with temperature sensors, and a Raspberry Pi with a Gertboard attached that connects to a receiver board. The enclosure transmits sensor data to the receiver board. The receiver passes the decoded data to the ATmega328P microcontroller on the Gertboard. I covered the transmission, via 434 MHz transmitter and receiver in my March 14 post. <a href="http://thepiandi.blogspot.com/2015/03/manchester-encodingdecoding-data.html">Check it out here</a>.</div>
<div style="margin-bottom: 0.1in;">The last piece of the data chain is to pass the data to the Raspberry Pi. A python program, running on the Raspberry Pi, is in charge of obtaining the measurements from the C++ program running on the Gertboard's ATmega328P. As long as the sensor enclosure is transmitting, the Gertboard receives the measurements. </div>
<div style="margin-bottom: 0.1in;"><b>If you wonder why I pass data to the Raspberry Pi it is because I can get graphs like this: </div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNx63q-LLXIvAJaHijAKU35Dcy2JUtNn2ZDuyYkbpTXgHBwW3L4lCmcfkQdkOz4rA8RE1uKvFjB138sKDFjLWe2ScXV2WX_8EgV597tFZ6BWUTRj2xNiH32r2162BWx-0Pf9g9H83KhiqU/s1600/ForBlog_black.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNx63q-LLXIvAJaHijAKU35Dcy2JUtNn2ZDuyYkbpTXgHBwW3L4lCmcfkQdkOz4rA8RE1uKvFjB138sKDFjLWe2ScXV2WX_8EgV597tFZ6BWUTRj2xNiH32r2162BWx-0Pf9g9H83KhiqU/s580/ForBlog_black.png" /></a>
<div style="margin-bottom: 0.1in;">I can get a log file like this (just the beginning of the file)<b>:</b></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3QObCuDbTGymBHH5FXGK3UlWlfaj35LZGeYOHUaA4noq_hgAraj-JmOxH0btJ0I5VMMkOI03eWNulCvdxmw4I4Jr43F2yUdV5aicwKCTLjtc1IpfYn3JhQ4zm8bSJ-vD47g_eeZdqwua-/s1600/LogFile.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3QObCuDbTGymBHH5FXGK3UlWlfaj35LZGeYOHUaA4noq_hgAraj-JmOxH0btJ0I5VMMkOI03eWNulCvdxmw4I4Jr43F2yUdV5aicwKCTLjtc1IpfYn3JhQ4zm8bSJ-vD47g_eeZdqwua-/s580/LogFile.JPG" /></a></div>
<div style="margin-bottom: 0.1in;">I can setup the measurement run with this graphical user interface I created<b>:</b></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEDQQTP4UGQFpwTAPk1rKfqz8Nm_x5A4wetHcEjcRI86d5jZQjGbmcOn0sTMwfLHr0Du1pt3ROEdT-AtI-VARa_9RkG7Rnd-L-wXrlcOq1Bcu_Rl3lX2XcEqBgLni2OWsCSdSvGRUGyEMs/s1600/GUI.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEDQQTP4UGQFpwTAPk1rKfqz8Nm_x5A4wetHcEjcRI86d5jZQjGbmcOn0sTMwfLHr0Du1pt3ROEdT-AtI-VARa_9RkG7Rnd-L-wXrlcOq1Bcu_Rl3lX2XcEqBgLni2OWsCSdSvGRUGyEMs/s580/GUI.JPG" /></a></div></b>
<h3>Data Captured By the Receiver</h3>
<div style="margin-bottom: 0.1in;">ROM codes, and 12 bytes of description for each DS18B20 sensor, are stored in the EEPROM of the enclosure's ATMega328P. One temperature sensor is permanently connected to the enclosure, but I can connect as many other sensors as I wish. However, the ROM codes and descriptions for those other sensors must be stored in the EEPROM. When I apply power to the enclosure, we find out what sensors are attached by attempting to read from the scratchpad of each sensor for which we have a ROM code. If the CRC passes, we know the sensor is connected. </div>
<div style="margin-bottom: 0.1in;">I have a full suite of ATmega328P, C++ sketches, for adding, editing, and removing sensor data from the EEPROM. <a href="https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/tree/master/DS18B20_Temperatur_%20Sensor">Check it out here.</a> I also wrote my own library for the DS18B20 temperature sensor, and other libraries. <a href="https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/tree/master/libraries"> Check out my libraries here.</a> </div>
<div style="margin-bottom: 0.1in;">Let's assume I have data for five sensors stored in the EEPROM and sensor's 1, 3, and 5 are connected to the enclosure. I command each sensor, in turn, to make a temperature measurement. When the measurement is available, we assemble 20 bytes of data (data for one sensor). The first byte is always the number of sensors that are connected to the enclosure. For our example, that number is 3. The next to the last byte is the number of the sensor which corresponds to its position in the EEPROM. In our example, that will be 1, 3, or 5. The other bytes correspond to the temperature measurement, high and low alarm temperature, and the sensor description. The last byte is the CRC. We continually make measurements running through each of the connected sensors. </div>
<div style="margin-bottom: 0.1in;">The receiver, continually, looks for valid data. If it recognizes synchronization pulses (<a href="http://thepiandi.blogspot.com/2015/03/manchester-encodingdecoding-data.html">see my March 14 post</a>), it sees that the data is valid. It decodes the 20 bytes of Manchester encoded data for the sensor that happened to be transmitting. It may be sensor 1, 3, or 5. It looks at the first byte of data to find the number of sensors in the measurement run. In this case it will be three. An array is initialized whose length is the number of sensors, three in our case, times the number of data bytes per measurement, which is 20. In our example, the array will be 60 bytes long. The data for the first sensor is placed in the array. Next, the receiver code looks for, and captures, data for the next two measurements. This data is appended to the array. Now we have 60 bytes of data. The order of the data may be for sensors 1, 3, and 5; or 3, 5, and 1; or 5, 1, and 3.</div>
<div style="margin-bottom: 0.1in;">After accumulating the 60 bytes, the receiver code looks to see if the Raspberry Pi's python program is requesting the data. If not, the data in the array is overwritten with the next series of measurements. There will be a minimum of one minute between requests from the Pi to the receiver (selected by the user). Depending upon the resolution of the sensor and how power is applied to the sensor (normal or parasitic) the receiver will have those 60 bytes available about every 300ms. to every 2200ms. Therefore, you can see that most of the measurements are lost.</div>
<h3>Receiver Code</h3>
<div style="margin-bottom: 0.1in;">I have taken another fragment of the C++ code running on the Gertboard's ATmega328P. <a href="https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/blob/master/Gertboard%20Arduino%20Sketches/Temp_RF_toPython_MultipleSensors_V2R3.ino">Visit here to see the entire script</a>. </div>
<script src="https://gist.github.com/RaspPiGuy/5f29078f091ca855deaa.js"></script>
<div style="margin-bottom: 0.1in;">The code fragment includes the function, "transmit_data()" that looks for a request from the Pi and transfers the data to the Pi. I also included some of the code in "loop()" to illustrate the sequence of events. </div>
<div style="margin-bottom: 0.1in;">To initiate a data transfer cycle, we first look for synchronizing pulses by running line 41 (see blog post of March 14 for this function). We stay here until we find valid synchronization. Once synchronization is confirmed, we move to line 42, the "manchester_data()" function. This will return data for one sensor - the sensor that was transmitting at the time. The code for the "manchester_data()" function can also be found at my March 14 post. If the CRC passes, we now read the first byte of the data to see how many sensors are connected to the enclosure. Now, that we know how many sensors, we can declare the array "xmit_data[]". This array will hold all of the data for all of the sensors for one measurement cycle. After populating "xmit_data[]" with the data from the one sensor we have acquired, we repeat "synchronize()" and "manchester_data()" for each of the other sensors in the run. Now, we have all of the data. Next is to see if the Raspberry Pi has called for the data. </div>
<div style="margin-bottom: 0.1in;">We are now down at line 68 assuming there were no CRC errors. Line 68 takes us to the function "transmit_data()". The function looks to see if there is anything on the ATmega's serial bus (line 15). If so, it is read and put into the array "buff[]" by implementing "Serial.readBytes()". We are looking for one character, and that character is "s". If we find the "s", we place all the data, one byte at a time, onto the serial bus (via the print statement in line 19). If there was no request from the Pi for data, the contents of "xmit_data[]" will be overwritten with new data.</div>
<h3>Python Code Running In the Raspberry Pi</h3>
<div style="margin-bottom: 0.1in;">The following is a fragment from a rather long program running on the Pi. The program handles setting up the log files for storing the data, sets up the graph parameters, obtains sensor information (description, high and low alarm settings, and resolution), calls the GUI program and incorporates the user responses, makes and records the temperatures, and creates the graphs. <a href="https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/blob/master/Python%20Programs%20Running%20On%20The%20Pi/GraphRemoteTemperature_V1R3.py">The entire program is here.</a> This program calls another python program that handles the graphical user interface. <a href="https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/blob/master/Python%20Programs%20Running%20On%20The%20Pi/GUI4GraphTemperature_V2R2.py">That program is here.</a></div>
<script src="https://gist.github.com/RaspPiGuy/06e5e8cd88717d6997cc.js"></script>
<div style="margin-bottom: 0.1in;">The function "number_of_sensors()" is called once to obtain the sensor information<b>:</b> description, alarms, and resolution. Then, it is called every time the program calls for temperature measurements. When the function exists, if there was valid data, all of the data from all of the sensors will be in the global array "recv_data[]". In addition, the function returns the number of sensors in the run. </div>
<div style="margin-bottom: 0.1in;">"number_of_sensors()" calls the function "retrieve_serial()". "retrieve_serial()" does the actual work of requesting data from the ATmega328P on the Gertboard, and retrieving the response from the Gertboard. When requested by "number_of_sensors()", it clears the serial port of lingering data, writes the character "s" to the serial port, and waits for a response from the Gertboard. It will check every second for data. If it sees no data, or if the length of the data does not equal a multiple of 20 bytes, it keeps looking. If it has not found valid data after 10 seconds, it gives up and returns "0". If valid data is seen, it returns the number of bytes received.</div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-44726596502521103712015-04-11T22:31:00.000-04:002015-04-11T22:31:52.461-04:00Printing Leading Characters With Arduino IDE Serial Monitor<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<div style="margin-bottom: 0.1in;">I have a blog post on calculating and checking the Cyclic Redundancy Check (CRC) byte when transmitting serial data. <a href="http://thepiandi.blogspot.com/2014/07/cyclic-redundancy-check-crc-of-ds18b20.html">Here is a link.</a> Near the bottom, is a sketch fragment of my CRC function and a table. The table illustrates how the CRC is calculated as the function progresses, bit, by bit, through the data. Here is the output I received from the Arduino IDE Serial Monitor<b>:</b> </div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSql7uPQTzDm_y_r28IOMDIPkhm8lW9wOpsGHf77Fk2nm3VFH9wbI0tZrX1w0l-boxwREqHBpjdo_cdxiVdrG1prH_H4ntPRXo7w7WIbHYT-2dUCFgUp160ib1zLKqUnBYpLMQXBAnORtR/s1600/NoleadingZeros.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSql7uPQTzDm_y_r28IOMDIPkhm8lW9wOpsGHf77Fk2nm3VFH9wbI0tZrX1w0l-boxwREqHBpjdo_cdxiVdrG1prH_H4ntPRXo7w7WIbHYT-2dUCFgUp160ib1zLKqUnBYpLMQXBAnORtR/s640/NoleadingZeros.JPG" /><div class = "caption"><i><center>Arduino IDE Serial Monitor Output Printing Binary Numbers</i></center></div></a></div>
<div style="margin-bottom: 0.1in;">That's really ugly. The serial monitor that is part of the Arduino IDE does not print leading zeros. I wanted to see those zeros. "CRC" is an integer, so has 16 bits. "inByte[i]" is 8 bits long. I wrote a small function to calculate how many leading zeros to print when printing a binary number. Then, I expanded it to to handle numbers of any base, and finally, to add any leading character, not only zeros. This is the output using my leading character function<b>:</b></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM5UldpPlbjzb3djUPr7iaNd5V5_NYq9E3lhUWyhfnVmxr03vQBYiRQNVUAkUWbye7WfntneNW-aXvBvbdcvpOn17xC7FxwJCcGeGZBp94LSWUkYQx-PQunwJAIabNWna8zXn7RZAp4OCd/s1600/LeadingZeros.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM5UldpPlbjzb3djUPr7iaNd5V5_NYq9E3lhUWyhfnVmxr03vQBYiRQNVUAkUWbye7WfntneNW-aXvBvbdcvpOn17xC7FxwJCcGeGZBp94LSWUkYQx-PQunwJAIabNWna8zXn7RZAp4OCd/s640/LeadingZeros.JPG" /><div class = "caption"><i><center>Serial Monitor Output Using My Leading Character Function</i></center></div></a></div>
<div style="margin-bottom: 0.1in;">My leading character function follows. It is amazingly simple. However, it's not universal. It does not handle minus signs or decimal points<b>:</b> </div>
<script src="https://gist.github.com/RaspPiGuy/8028e5a2bbe9d467d142.js"></script>
<div style="margin-bottom: 0.1in;">The "pow" operator raises the value in "base" to the power of "position" - 1. For example, if you wish to print a 16 bit binary number, "factor" will be 2<sup>15</sup>. You can see that "factor" can become a very large number, especially if you are dealing with decimal or hex numbers. Consequently, "factor" is a double, a floating point data type. However, the function may not work if "factor" wants to be too large. Just imagine if you wanted 16 characters of a decimal number. "factor" will be 1,000,000,000,000,000. A double data type for all Arduinos beside the Due is four bytes in length, not enough bytes to express 10<sup>15</sup>. The Due may be able to handle 10<sup>15</sup> - it's double is 8 bytes in length.</div>
<div style="margin-bottom: 0.1in;">Leading spaces can come in handy for printing dates. You can use it to line up dates like this<b>:</b></div>
<ul>
<li>April 9, 2015
<li>April 10, 2015
</ul>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-50238896285813694702015-03-14T16:16:00.000-04:002015-03-14T16:27:29.029-04:00Manchester Encoding/Decoding Data Between Devices<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<div style="margin-bottom: 0.1in;">My most recent posts have been about making temperature measurements with the Maxim/Dallas DS18B20 temperature sensors. I have an enclosure with a 2 line by 16 character display that can connect to many of these sensors. </div>
<div style="margin-bottom: 0.1in;">If I want to go beyond merely displaying the temperature, and wish to record and graph the temperature, I wirelessly transmit the data from the enclosure to my Raspberry Pi. Consequently, I need some sort of transmitter and receiver. The transmitter and receiver I chose operate at 434MHz and are small and simple. Both are available from Sparkfun Electronics. </div>
<div style="margin-bottom: 0.2in;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuM5m-84qwjyqY4RNoIiZ47K0MG-kHLAViSpp_z_5DPvK5xYe9Gji-hDekDQqWudJAGjddPe2akOlM4rJUO0xkiOnQZu3OYKq0Mj_8syEJp2_0PcRNiKIRYT62aeOqbG4UVKlW5wgAHskk/s1600/TemperatureSensorBox.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuM5m-84qwjyqY4RNoIiZ47K0MG-kHLAViSpp_z_5DPvK5xYe9Gji-hDekDQqWudJAGjddPe2akOlM4rJUO0xkiOnQZu3OYKq0Mj_8syEJp2_0PcRNiKIRYT62aeOqbG4UVKlW5wgAHskk/s320/TemperatureSensorBox.jpg" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6FQJk-Mv04Mkj9U4D5DVyx_6zgqQc4_n_SBH6JRknyHvziQ-TyHDy1QV_4K0i6ntPRiQFsd4Ik7hHcqcDXAXVAUaojZesZPl-5QOw_XXlpzPdETjrTWhwioS32b-86z_eHFDG13pQNj1v/s1600/Receiver.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6FQJk-Mv04Mkj9U4D5DVyx_6zgqQc4_n_SBH6JRknyHvziQ-TyHDy1QV_4K0i6ntPRiQFsd4Ik7hHcqcDXAXVAUaojZesZPl-5QOw_XXlpzPdETjrTWhwioS32b-86z_eHFDG13pQNj1v/s320/Receiver.jpg" /><div class = "caption"><i><center>On the left: Temperature Sensor Enclosure. On the right, 454 MHz Receiver connecting to the Gertboard. The Gertboard plugs into the RaspberryPi (seen at the very top). </i></center></div></a></div>
<div style="margin-bottom: 0.2in;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi571dx7rSKahd2cRJqCvCmTQrgikvJYQP4Sq2cAGtIRfp8bd-n67OajwS1S4toUy4QI08V-nCopBOrPJPsEt987s0psG4s3lCm3G5xphgGTl0dWoiwO3vEcxRPBEyU8MUcFmx1WxIwtgnV/s1600/SparkfunTransmitter.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi571dx7rSKahd2cRJqCvCmTQrgikvJYQP4Sq2cAGtIRfp8bd-n67OajwS1S4toUy4QI08V-nCopBOrPJPsEt987s0psG4s3lCm3G5xphgGTl0dWoiwO3vEcxRPBEyU8MUcFmx1WxIwtgnV/s250/SparkfunTransmitter.jpg" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkBFTcjIF-hzNRC-5hO2UdrezZ3vdshAFxljKPveT0zI_T9RC0htkyhRmCrip2H_DI_HmZPbX6JCgXoDqvXAg4sWW_77k8izkvuxjS-e5V1mExYKULAIyvlM3V8xq7YlPJ3igh6zGZsSzm/s1600/Sparkfun_Receiver.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkBFTcjIF-hzNRC-5hO2UdrezZ3vdshAFxljKPveT0zI_T9RC0htkyhRmCrip2H_DI_HmZPbX6JCgXoDqvXAg4sWW_77k8izkvuxjS-e5V1mExYKULAIyvlM3V8xq7YlPJ3igh6zGZsSzm/s250/Sparkfun_Receiver.jpg" /><div class = "caption"><i><center>Sparkfun's 454 MHz Transmitter on the left. Their 454 MHz Receiver on the right.</i></center></div></a></div>
<div style="margin-bottom: 0.1in;">I don't transmit directly to the Pi because I want the receiving device to be dedicated to processing the received data, A microcontroller is ideal for that type of task. A multitasking microprocessor, like the Pi, cannot do this very well - it doesn't focus on one task. The Pi, however, is really good at logging and storing data. My Pi has a marvelous capability to graph temperatures (See my posts about RRDTool).</div>
<div style="margin-bottom: 0.1in;">My receiver connects to my Gertboard, which, in turn, connects to my Pi. The Gertboard has the same microcontroller device as an Arduino Uno<b>:</b> an Atmel ATmega328P. My temperature measuring enclosure also has the same microcontroller.</div>
<div style="margin-bottom: 0.1in;">My next post will tell how my data gets from the Gertboard to the Raspberry Pi. It's an interesting story and deserves a post of its own.</div>
<h3>Asynchronous Data Transfer</h3>
<div style="margin-bottom: 0.1in;">I am sending data asynchronously, it can start at any time. The receiver must be able to find the start of a burst of data. For that to happen, I precede the data with a synchronization pattern. This pattern is chosen so that it can never be confused with the actual data. I accomplish this by encoding the actual data in a way that there are never more than two logic 1's or two logic 0's together. My synchronization pattern, then, must have <b>more</b> than two 1's and/or two 0's, together. </div>
<div style="margin-bottom: 0.1in;">I use Manchester encoding with my data, which is a standard protocol. Every logic 1 in the data is replaced with a 01, while a logic 0 becomes a 10. You can see how this avoids more than two 0's or 1's together. For example<b>:</b> 0000 becomes 10101010. Only where there is a change in logic level will you find two 0's or 1's together. For example<b>:</b> 001100 becomes 101001011010. </div>
<div style="margin-bottom: 0.1in;">There is a good reason for avoiding long strings of 1's or 0's<b>:</b> the receiver will see this an an interruption of data. The receiver has an automatic gain control, and if it sees no data, it will increase its gain to the maximum. The receiver will then output rail to rail thermal noise (See the beginning of the yellow scope trace below).</div>
<div style="margin-bottom: 0.1in;">The disadvantage of this scheme is that I must transmit two bits for every single bit of data. </div>
<div style="margin-bottom: 0.1in;">Here is what the start of my data looks like on the scope:</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2bbiLtjoZzIZzazsu4RmSijb2FpvPXeMJB5ap8csfAGmQzruGMYa9zO2PCBMDq8tnWj_e4vSSUwMD_BhLpu3ra6k7SMBDi4VF4Nc3Xy9oYibxpZZjCoNO4-Y8d0aF_gGtVLBAHMrCKLNv/s1600/TransmittedAndReceivedData.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2bbiLtjoZzIZzazsu4RmSijb2FpvPXeMJB5ap8csfAGmQzruGMYa9zO2PCBMDq8tnWj_e4vSSUwMD_BhLpu3ra6k7SMBDi4VF4Nc3Xy9oYibxpZZjCoNO4-Y8d0aF_gGtVLBAHMrCKLNv/s320/TransmittedAndReceivedData.jpg" /><div class = "caption"><i><center>Red trace: Data to the Transmitter. Yellow trace: Received Data</i></center></div></a></div></div>
<div style="margin-bottom: 0.1in;">The upper trace (red) is the data to the transmitter, while the lower trace (yellow) is the received data at the Gertboard. </div>
<div style="margin-bottom: 0.1in;">After every burst of transmitted data, there is a lapse of several hundred milliseconds (transmitter outputs 0V). During this time one if the temperature sensors makes its measurement and converts the measurement to two bytes of digital data. At some point during this dead time, the receiver's automatic gain control goes to its maximum. You can see the resulting noise in the beginning of the trace of the receiver's output. </div>
<div style="margin-bottom: 0.1in;">You can clearly see the two synchronization pulses in both the transmitted and received data. The synchronization pulses consist of four high bits followed by four low bits. The synchronization pulses are preceded by a 101010 pattern. The receiver will recognize this pattern as actual data and will adjust its automatic gain control. There is 10 pattern following the synchronization pulses. The start of the Manchester encoded data follows that. </div>
<h3>My Data</h3>
<div style="margin-bottom: 0.1in;">I am sending 20 bytes of data with each measurement<b>:</b></div>
<ul>
<li>byte 0: Number of sensors being accessed
<li>byte 1 and 2: From the DS18B20 Scrathpad - the measured temperature
<li>byte 3: From the DS18B20 Scrathpad - Upper temperature alarm. Previously set by the user
<li>byte 4: From the DS18B20 Scrathpad - Lower temperature alarm. Previously set by the user
<li>byte 5: From the DS18B20 Scrathpad - Resolution (9, 10, 11, or 12 bits). Previously set by the user
<li>byte 6 through 17: From the ATmeta328P EEPROM - Sensor Description. Previously set by the user
<li>byte 18: The number of the sensor as determined by its position in the ATmega328P's EEPROM.
<li>byte 19: Cyclic Redundancy Check (CRC) byte calculated from the previous 19 bytes.
</ul>
<div style="margin-bottom: 0.1in;">Except for byte 0, each burst of data contains the data from one temperature sensor. Each sensor is accessed, in turn, before starting with the first sensor, again. </div>
<h3>Transmit Code</h3>
<div style="margin-bottom: 0.1in;">The following is a fragment of the code I usually run on my Temperature Sensor Enclosure. I say usually because I can upload other code to the box via its attached USB/FTDI port. <a href="https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/blob/master/RF%20Transceiver/Xmit2PiWithLCD_AutoSelect/Xmit2PiWithLCD_AutoSelect.ino">The entire code can be seen here: </a></div>
<div style="margin-bottom: 0.2in;">The enclosure has one permanently mounted DS18B20 temperature sensor and three receptacles for plugging in more sensors. It is possible to connect hundreds of these sensors to the enclosure (normal and parasitic power is supported). However, I only have room in the ATmega's EEPROM for the ROM codes and descriptions of 50 sensors. In the photo above, you can see I have two DS18B20 cables attached to the box. The code auto-detects the sensors when the code starts. As long as the ROM code and description of the sensor is in the EEPROM, the code will include the sensor in the measurements and in the transmitted data. If I have a new sensor, I have code to upload to the enclosure that will detect new sensors and will prompt for description, and alarm and resolution settings. </div>
<div style="margin-bottom: 0.1in;"><script src="https://gist.github.com/RaspPiGuy/c70016090c94e6b3e9de.js"></script><div class = "caption"><font color = "blue"><i><center>Code Fragment of Sketch Running On ATmega328P in Enclosure To Transmit Data to Gertboard.</i></center></font color></div></div>
<div style="margin-bottom: 0.1in;">Whenever we are ready to transmit data, the function "synchronize()" is called, followed by 20 calls to function "send_data()" - one call for each data byte in the burst. The timing is established by the global variable "bit_time". It is calculated to send data at 600 baud (1200 bps - remember it takes 2 Manchester encoded bits to send one bit of data). </div>
<div style="margin-bottom: 0.1in;">Note my use of ATmega register programming rather than "bitMode" and "digitalWrite". <a href="http://thepiandi.blogspot.com/2014_01_01_archive.html">I have a whole tutorial about register programming at by blog here:</a> </div>
<h3>Receive Code</h3>
<div style="margin-bottom: 0.1in;">The following is a fragment of code that runs on my Gertboard that receives Manchester encoded data from my Temperature Sensor Enclosure. <a href="https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/blob/master/Gertboard%20Arduino%20Sketches/Temp_RF_toPython_MultipleSensors_V2R2.ino">The entire code can be found here.</a></div>
<div style="margin-bottom: 0.1in;"><script src="https://gist.github.com/RaspPiGuy/7c4bc2825863d1e60ada.js"></script><div class = "caption"><font color = "blue"><i><center>Code Fragment of Sketch Running On ATmega328P on the Gertboard To Receive Data from the Temperature Sensor Enclosure.</i></center></font color></div></div>
<div style="margin-bottom: 0.1in;">While the transmit code is pretty easy to figure out, the receive code is interesting and bears some analysis. First, it illustrates the use of ATmega interrupts. Not shown in the code fragment are two lines in setup()<b>:</b></div>
<div style="margin-bottom: 0.0in;">EICRA = B00000001; // Any change will trigger interrupt</div>
<div style="margin-bottom: 0.1in;">EIMSK = B00000001; // Enable INT0 interrupt</div>
<div style="margin-bottom: 0.1in;">This means that <b>any</b> change in logic level of the ATmeta328P pin connected to the receiver circuitry will trigger an interrupt. Put another way<b>:</b> if the logic level changes from 0 (0V) to 1 (3.3V) or from 1 (3.3V) to 0 (0V), an interrupt is issued. </div>
<div style="margin-bottom: 0.1in;">Lines 18 - 20 constitutes the Interrupt Service Routine. Whenever an interrupt is issued, the variable "found_transistion" becomes true. We set "found_transistion" false, in lines 34, 41, 66, and 75. When the "while" statements in line 35, 43, 67, and 77 are reached, processing is halted until the interrupt occurs. Using the "time" and "duration" variables and the "micro()" function, the time between interrupts (corresponds to the time between transitions) can be determined. </div>
<h3>Analyzing The Receive Data</h3>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlsAZ3wxavkO9IRBopmVcoRLu3rGp_weVAbycX8_2-S5fqM4PLvUBGz1Mp_UylqIWCy6NBi3bDmxw8UjL6SAPeV51hW-Sx5AxqQD_9Knr7i0s2fi7AQ7wPs5VkFLrz7ciV_43DCPmCXeXv/s1600/ManchesterDecoding.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlsAZ3wxavkO9IRBopmVcoRLu3rGp_weVAbycX8_2-S5fqM4PLvUBGz1Mp_UylqIWCy6NBi3bDmxw8UjL6SAPeV51hW-Sx5AxqQD_9Knr7i0s2fi7AQ7wPs5VkFLrz7ciV_43DCPmCXeXv/s600/ManchesterDecoding.jpg" /><div class = "caption"><font color = "blue"><i><center>Synchronization and Made-up User Data</i></center></font color></div></a></div>
<div style="margin-bottom: 0.1in;">When sychronize() is called from the main program, it looks for a positive pulse of 4 bits in duration (plus or minus 10%). It keeps looking until it find it. If it next finds a negative pulse of 4 bits in duration (plus or minus 10%), it exits the routine. It will stay in this function until it is satisfied it has found the synchronization pattern. </div>
<div style="margin-bottom: 0.1in;">Once we drop out of the sychronize() function, the manchester_data() function is called. We stay in that function until 20 bytes are received. Looking at the waveform above, we start in the function at point "c". Next we look for one more transistion (lines 66 and 67) to bring us to point "d".</div>
<div style="margin-bottom: 0.1in;">We look for the actual received data by entering the outer "do" loop at line 72, performing the inner "do" loop (line 74) 20 times. The logic level of each bit of data we find is tracked by the variable "present_bit". This starts as 0 because the 10 pattern following the synchronization pulses is equivalent to a Manchester code of 0. </div>
<div style="margin-bottom: 0.1in;"> We are at point "d" looking for the next transition which occurs at point "e". Using the threshold of 1.5 times the time of one bit (in global variable bit_time), we determine if we have encountered a change in logic level from the original 0 to a 1. Since the time from point "d" to "e" is obviously less than the threshold, we have not encountered a change in logic level. Therefore, the first bit received is a 0. The "if/else" statements in lines 80 to 86 determine the actions taken if we do exceed, or do not exceed the threshold. Since we have not, "present_bit" does not change and the variable "no_clocks" is incremented by 1. </div>
<div style="margin-bottom: 0.1in;">The variable "no_clocks" has two functions. First, it indicates when we have received a bit of data. Since we must receive two bits of Manchester encoded data for each bit of sensor data, we take no action if "no_clocks" is an odd number ("if" statements lines 87 to 90). If "no_clocks" is even, we capture the last bit by shifting the contents of variable "hold_byte" to the left, and inserting the value of "present_bit" at the least significant position of "hold_byte". </div>
<div style="margin-bottom: 0.1in;">The second function of "no_clocks" is to tell us when we have received an entire byte of sensor data. This will be the case if "no_clocks" reaches 16. If that is the case, the value of "hold_byte" is transferred to the next byte of the array "frame[]". When we have received all 20 bytes of "frame[]" we exit the function. </div>
<div style="margin-bottom: 0.1in;">When last we were looking at the waveform, we were at point "e". We return to the beginning of the inner "do" loop to look for the next transition (point "f"). The time from "e" to "f" is also less than the threshold. We return back to the beginning of the inner do loop and find the next transition (point "f" to "g"). This time we find the threshold is exceeded so the value of "present_bit" flips to a 1 and "no_clocks" increments by 2. I think the action is easy to follow from here.</div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-17934636757859785652015-03-09T13:06:00.001-04:002015-03-09T13:07:35.821-04:00Get Rid of MaAfee On Your Brand New Computer<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<div style="margin-bottom: 0.1in;">I just purchased a new Windows laptop. Between all the bloat and the pre-installation of McAfee I was tempted to reformat the hard disk, purchase a copy of Windows 8.1, and start from scratch.</div>
<div style="margin-bottom: 0.1in;">What a racket McAfee has. They give you a free subscription for a couple of months. So what do you do when that expires? I would bet the vast majority of people either do without virus protection, or pay McAfee every year to maintain their protection. Nearly everyone knows the dangers of being unprotected, so I would guess most simply pay McAfee.</div>
<div style="margin-bottom: 0.1in;">I want the free Microsoft Windows Defender as my virus protection. With McAfee present, Defender is turned off. With a little web search, I found it was quite easy to remove McAfee and turn on Defender.</div>
<div style="margin-bottom: 0.1in;"><a href="http://service.mcafee.com/FAQDocument.aspx?id=TS101331">Everything you need to know to remove McAfee comes from this McAfee document</a>.</div>
<div style="margin-bottom: 0.1in;">I added one step to the process. I turned off my network connection.</div>
<div style="margin-bottom: 0.1in;">This all applies to a new computer with Windows 8.1. It turned out to be really simple and painless. Here is what I did<b>:</b></div>
<ol>
<li>Downloaded the McAfee Consumer Product Removal Tool (MCPR) - main paragraph 2a. from the link I gave you.
<li>Removed computer from my network because next step removes your protection.
<li>Uninstall McAfee - Main paragraph 1. from the link. No problems here.
<li>Find where you stored the MCPR.exe and run it. Just answer the questions asked. The prompt in paragraph 2f. never appeared so I did not have to deal with it.
<li>When you see "CleanUp Successful" reboot your computer.
<li>When you are up and running again connect yourself to your network.
</ol>
<div style="margin-bottom: 0.1in;">Check the action center (white flag in the notification area of the taskbar). Click on "Open Action Center" and then click on "Security". You will see that your firewall is protected by Windows and your virus and spyware protection is now provided by Windows Defender. You don't have to do anything to turn it on. </div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-44019924231577475712014-12-16T17:01:00.000-05:002014-12-19T10:43:43.689-05:00Jig To Load a Bootloader and Upload Sketches To ATmega328P<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<style>
h3 {margin-bottom: 0.1in;}
</style>
<div style="margin-bottom: 0.1in;"><b>Note:</b> I only write about what I know. Although there are many Arduinos and Arduino type products, I only have experience with the Arduino Uno Rev3. Likewise, the only Atmel microcontroller I know is the ATmega328P. </div>
<h3>A Little Background (well not so little)</h3>
<div style="margin-bottom: 0.1in;">I have Atmel ATmega328P microcontrollers on two devices: An Arduino Uno (Rev 3), and a Gertboard. The Gertboard connects to, and is programmed by, my Raspberry Pi. In both cases the microcontroller is in a socket, so is removable. I have developed applications for both where I needed to remove the ATmega328P and install it in another device. I use the Arduino IDE system to develop sketches on both the Arduino and the Gertboard/Raspberry Pi. There is more on the Gertboard at the end of this post.</div>
<div style="margin-bottom: 0.1in;">I developed a camera remote control using the Gertboard and removed the programmed ATmega chip and installed it on a circuit board. The circuit board, a 434MHz transmitter, and a motion detector were mounted in a box. <a href="http://thepiandi.blogspot.com/2014/01/camera-remote-control-free-to-move.html">I reported on that project in this blog entry</a>. </div>
<div style="margin-bottom: 0.1in;">I am completing a project that uses both the Arduino and the Gertboard/Raspberry Pi. In this case, it is the sketch developed on the Arduino that must run on an ATmega328P that is removed from the Arduino. This project, that I will report on later, requires the ability to communicate with the ATmega328P once it is installed in my mobile device. </div>
<div style="margin-bottom: 0.1in;">Both projects required me to program a new ATmega328P IC. However, you can not just insert a new chip on the Arduino or Gertboard and upload sketches to it. Out of the box, the microcontroller will not use the external 16MHz crystal of the Arduino or the 12MHz resonator of the Gertboard. It will use its internal 8MHz RC oscillator frequency reference and then divide that frequency by 8. The resulting clock frequency will be 1MHz.</div>
<div style="margin-bottom: 0.1in;">In order to change the clock source, you must change the logic level of a couple of "fuse" bits. I use "" around the word fuse, because the term is actually a carryover from the time when ICs, like microcontrollers, had actual fuses. Each fuse would control the logic level of one bit. If the fuse was blown, the bit would be a 0, if not blown it would be a 1. You could always change a 1 to a 0, by blowing the fuse, but you had no way to change a 0 to a 1. If you wanted a 1, but programmed a 0, in error, you had to replace the chip. That is not the case today. </div>
<div style="margin-bottom: 0.1in;">Now, "fuse" bits can be changed from 1 to 0 and 0 to 1 anytime. The ATmega328P has three, eight bit bytes of these "fuse" bits. They control different functions and leave the factory in a default configuration. In addition, there is a byte (8 bits) of lock bits. More on these later. To setup a new ATmega328P for the Gertboard, you run a program on the Raspberry Pi called avrsetup. All this program does is to use avrdude to set the lock bits and the fuse bits. It leaves all bits not concerned with the clock frequency to their default settings. The four bits that select the clock source are changed from "Calibrated RC Internal Oscillator" to "Full Swing Crystal Oscillator". And, the divide by 8 function is turned off. Avrdude is like an operating system for the Atmel microcontrollers. All programming of the microcontrollers are done through avrdude even if you use the Arduino IDE. </div>
<div style="margin-bottom: 0.1in;">For the Gertboard/Raspberry Pi, setting those fuse bits is all you have to do to use a new ATmetga328P. That is not the case with the Arduino. A new ATmega328P for the Arduino needs those same fuse bit changes and needs one more thing<b>:</b> a bootloader installed. What is a bootloader, and why doesn't the Gertboard need one? </div>
<div style="margin-bottom: 0.1in;">When you upload a sketch to the flash memory of the ATmega328P, there are two direct ways. One is to use a parallel configuration, which I will not mention further (just going to forget it exists). The other is to use the chip's SPI (Serial Peripheral Interface) bus. This synchronous, serial, bus consists of four lines: SCK (Serial Clock), SS (Slave Select), MOSI (Master Out Slave In), and MISO (Master In Slave Out). I upload sketches to the Gertboard via the SPI bus. The Raspberry Pi is the Master, the ATmega328P on the Gertboard is the Slave. <b>Since the direct programming method is employed, no bootloader is necessary.</b></div>
<div style="margin-bottom: 0.1in;">Atmel, in their wisdom, realized that not everyone would like to use the SPI bus, but would wish to use the more universal serial bus (or something else). The serial bus interface has several names such as RS232 and UART. It consists of several signals<b>:</b> TX (transmitted data) and RX (received data). The TX of the one device is connected to the RX of the other device, and RX of the first device is connected to TX of the second device. There are more signals, but, typically, they are not used. However, a signal, DTR (data terminal ready), for example, may be used to reset the ATmega328P. Once the ATmega328P is reset, it will start running any sketch loaded in flash from its beginning. </div>
<div style="margin-bottom: 0.1in;">Atmel provided an area of flash memory for the user to install code allowing the rest of the flash memory to be uploaded via the serial bus. This code is the bootloader. For the ATmega328P, it can take up as much as 2 Kbytes of the 32 Kbytes of flash memory. The flash memory, not reserved for the bootloader, is the Application memory. Once the bootloader is loaded, it can load a new sketch into the Application memory via the RX and TX connections of the serial bus.</div>
<div style="margin-bottom: 0.1in;">So, how do you get the bootloader loaded in a new ATmega328P? It requires hardware and software. Since a new ATmega328P has no bootloader, the bootloader must be installed from the SPI bus - the direct, primary, interface to the chip. That means you need an in-circuit programmer. There are inexpensive, commercial, units available like the USBtinyISP. They have USB on one end and the four SPI connections on the other end (SCK, SS, MOSI, and MISO), plus power and ground. They have a 6 pin ribbon cable and connector that plugs into your target device that contains the microcontroller chip you want to access. There is a standard 6 pin SPI configuration that receives the ribbon cable connector. My Arduino Uno has two of these 6 pin connectors, one for the ATmega16U2 and the other for the ATmega328P. You can install a new ATmega328P on your Arduino Uno and connect a programmer to it to upload the bootloader. But, I don't do that.</div>
<div style="margin-bottom: 0.1in;">I have no experience with the aforementioned programmers so I will not discuss them. There is another programmer that works really well - and I have experience with that one. This programmer is the Arduino itself. You can't use it to load a bootloader on its own ATmega328P, but it can be used to install a bootloader on another Arduino's ATmega328P. However, I do a variation of that. I use the Arduino Uno to install the bootloader on an ATmega328P that is on a jig I made. This is the jig that is the subject of this blog post. </div>
<div style="margin-bottom: 0.0in;">Now we need some software. There are two pieces of this. One piece is the bootloader itself. The Arduino IDE package has copies of the bootloaders. There are different bootloaders for the different ATmega devices and the different Arduinos. The other piece of software is the software to load the bootloader. This software is a sketch running on my Arduino Uno that is used as a programmer. This software must do several things. I have not studied this software to know how it works, but from my knowledge of the ATmega328P, I know it must do the following:</div>
<ul>
<li>Program the fuse bits to select the clock source to "Full Swing Crystal Oscillator" and turn off the clock divide by 8.
<li>Set the Lock bits to allow programming of the bootloader in the Boot Flash Section
<li>Set the fuse bits to the amount of flash memory devoted to the Boot Flash Section (up to 2 KBytes)
<li>Upload the bootloader program to the Boot Flash Section
<li>Set the lock bits so the Boot Flash Section can no longer be written to, protecting it from being overwritten.
</ul>
<div style="margin-bottom: 0.1in;">There is one last point to consider before moving on to the details of my programming jig. Could there be an Arduino that programs the microcontroller directly over the SPI bus? Certainly. There are ICs that convert USB to SPI. That would eliminate the bootloader. We are forgetting one thing though<b>:</b> How do you communicate with a sketch? For example, a sketch that requires you to answer some questions before proceeding. The answer is the Serial Monitor. Access to the Serial Monitor is via the same interface the Arduino uses to upload sketchs - the same TX and RX connections to the ATmega328P. </div>
<div style="margin-bottom: 0.1in;">For the Gertboard, the Serial Monitor button exists on the Arduino IDE running on the Raspberry Pi. However, it does not work. A separate connection to the ATmega328P's UART must be made. Consequently, the Raspberry Pi/Gertboard requires six signal connections<b>:</b> SCK, MOSI, MISO, SS, and TX and RX. The Arduino UNO only has two ATmega328P signal connections<b>:</b> TX and RX. For the Gertboard, I have to open a separate terminal window and run a terminal program to communicate with a running sketch. All-in-all, the loss of a little flash memory to the bootloader seems worthwhile.</div>
<h3>An ATmega328P Programming Jig</h3>
<div style="margin-bottom: 0.1in;">The following is the schematics and board layout diagram for my jig<b>:</b></div>
<div style="margin-bottom: 0.2in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8wAI3T_iPTDn7mxJU3qo36ThgFJ4z8undz9B2bpKhOv33qxHRDrCW0XcbCqeMLOyHLYWE9ZxgGTnhwQ2E96uO45HMI8MdfrIvXSu1SLvCYvgo1XIVdtg_xFgyCfc2mjVZ6V3i3xN95dc_/s1600/Programmer+Schematic+For+Blog.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8wAI3T_iPTDn7mxJU3qo36ThgFJ4z8undz9B2bpKhOv33qxHRDrCW0XcbCqeMLOyHLYWE9ZxgGTnhwQ2E96uO45HMI8MdfrIvXSu1SLvCYvgo1XIVdtg_xFgyCfc2mjVZ6V3i3xN95dc_/s580/Programmer+Schematic+For+Blog.JPG" /></a><div class = "caption"><i>Schematics For ATmega328P Programmer</i></div></div></div>
<div style="margin-bottom: 0.1in;">Here is the layout of the board with components and wiring<b>:</b></div>
<div style="margin-bottom: 0.2in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8nByV58t19y-5zfwpHQXeRVfYZALRzyVn2qORWoppD6ooNWbQr8y3GDSHBnd9KVPgP0BYVfbeWcxk56FSzCmhcRw6gedmPxbiYJPMVDqUliDmpxHgAqSYEpr5NZvB2TaUCMENugrx-3BB/s1600/Programmer+Layout+For+Blog.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8nByV58t19y-5zfwpHQXeRVfYZALRzyVn2qORWoppD6ooNWbQr8y3GDSHBnd9KVPgP0BYVfbeWcxk56FSzCmhcRw6gedmPxbiYJPMVDqUliDmpxHgAqSYEpr5NZvB2TaUCMENugrx-3BB/s640/Programmer+Layout+For+Blog.JPG" /></a><div class = "caption"><i>Board Layout For The ATmega328P Programmer</i></div></div></div>
<div style="margin-bottom: 0.1in;">Looking at the board layout, the ATmega328P sits in a 28 pin ZIF socket (all that green in the diagram). This allows an IC to be quickly inserted and removed. <a href="https://www.sparkfun.com/products/9175">Check out the product page from Sparkfun.</a></div>
<div style="margin-bottom: 0.1in;">The connector pins labeled SPI are for female - female jumper wires. This interface connects to the Raspberry Pi or to the Arduino Uno. Connections to the Raspberry Pi are to set the fusebits on an ATmega328P, and to load sketches developed on the Gertboard. The connections to the Arduino UNO are only to install a bootloader on an ATmega328P. </div>
<div style="margin-bottom: 0.1in;">Note the interface labeled "FTDI". This interface is used to upload sketches to an ATmega328P (must have the bootloader installed) that I have developed on my Arduino. In addition, it provides access to the Arduino IDE Serial Monitor, allowing us to communicate with a program running on the jig's ATmega328P. FTDI is the name of a chip manufacturer that makes USB to Serial ICs. The FTDI interface on my jig connects to a <a href="https://www.sparkfun.com/products/9873">Sparkfun FTDI Basic breakout board</a>. This small board has a mini USB on one end and a six pin female connector on the other that plugs directly onto my jig.</div>
<div style="margin-bottom: 0.1in;">There is a three pin female connector labeled resonator. Since the Gertboard and the Arduino Uno operate on different frequencies, the connector allows a 12MHz resonator to be connected for the Gertboard sketches and a 16MHz resonator for the Arduino operations.</div>
<div style="margin-bottom: 0.1in;">There are two LEDs on the jig. The green one lights whenever power is applied to the jig. 5V can come from the FTDI board or the Arduino Uno. The Gertboard will supply 3.3V. The red LED is a sanity check and is connected to PB1 of the jig (this corresponds to pin 9 of the Arduino). After loading a bootloader, I can check if I can upload a sketch to a new ATmega528P by running a version of Blink. Anytime I need to check the jig or my connections, I can program that red LED. </div>
<h3>Parts List</h3>
<ul>
<li>Prototype Breadboard PCB, half size<b>:</b> Adafruit 1609, $4.50
<li>ZIP Socket, 28 pin<b>:</b> Sparkfun PRT-09175, $2.95
<li>Right Angle Header Strip for FTDI and SPI<b>:</b> Mouser 571-9-103323-0, $2.24 for a strip of 40 pins
<li>ATmega328P Microcontroller<b>:</b> Mouser 556-ATmega329K-PU, $3.55
<li>Socket strip for Resonators<b>:</b> Digikey 1212-1125-ND, $3.89 for a strip of 64. Perfect socket for resonator pins
<li>16 MHz Resonator<b>:</b> Mouser 520-ZTT1600MX, $0.50
<li>12 MHz Resonator<b>:</b> Mouser 520-ZTT1200MX, $0.50
<li>Red LED - clear housing<b>:</b> Digikey C503B-RCN-CW0Z0AA1-ND, $0.15
<li>Red Green - clear housing<b>:</b> Digikey C503B-GCS-CY0C0791-ND, $0.24
<li>10μF, 16V Tantalum capacitor<b>:</b> Mouser 581-TAP106K016CRW, $0.53
<li>0.1μF 100V Ceramic capacitor<b>:</b> Mouser 1C20X7R104K100B, $0.18 ea.
<li>1N4148 diode<b>:</b> Mouser 512-1N4148, $0.10
<li>10KΩ Metal Film Resistor<b>:</b> Mouser 71-RN55D-F-10K, $0.10
<li>1KΩ Metal Film Resistor<b>:</b> Mouser 71-RN55D1001F/R, $0.10 ea.
</ul>
<div style="margin-bottom: 0.1in;">I use LEDs with clear bodies. I anticipate using LEDs in battery powered projects so I want to minimize the current consumed by LEDs. Normally, you calculate the series resistor to deliver about 10ma. of current to drive the LED on. A resistor of about 330Ω is commonly used. The LEDs with the clear housings require much less current so I typically use a 1KΩ series resistor (about 2ma.). Even that can seem too bright, I might try 2KΩ on my next project. </div>
<h3>Using the Jig</h3>
<div style="margin-bottom: 0.2in;">Diagram used for all situations follows:</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYmaDF3E7zON-qGcW4pcOdbIGdelM58qkIB-4w8i1DWutccLBY6bsMK8MM2EOS3p_K17rZ9-GyhjA8UfphJoKjMaUZtsPlGZOf0x-8JwTUXNwNctI7S7d0slC0ELRcvBeoejHmpN0B-a4_/s1600/Progrogramming+Setup.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYmaDF3E7zON-qGcW4pcOdbIGdelM58qkIB-4w8i1DWutccLBY6bsMK8MM2EOS3p_K17rZ9-GyhjA8UfphJoKjMaUZtsPlGZOf0x-8JwTUXNwNctI7S7d0slC0ELRcvBeoejHmpN0B-a4_/s580/Progrogramming+Setup.JPG" /></a><div class = "caption"><i>Connecting The Programming Jig</i></div></div></div>
<h3>Installing a Bootloader</h3>
<div style="margin-bottom: 0.1in;">Make connections as in the diagram above from the jig's SPI connector to the Arduino. Make sure there is a 16MHz resonator installed on the jig. Install an ATmega328P on the fixture. By the way, I probably should have mentioned it before, but do NOT use a ATmega328 unless you are capable of adding support for the device in avrdude and the Arduino IDE. The two devices have different signatures so the ATmega328 will not be recognized unless you are capable and willing to make the software changes I mentioned. The two devices are about the same but the "P" version runs at lower power.</div>
<div style="margin-bottom: 0.0in;">Do the following from the Arduino IDE<b>:</b></div>
<ol>
<li>Upload the sketch ArduinoISP<b>: Files\Examples\ArduinoISP</b>.
<li>Select the Arduino Uno board (selects the bootloader for the ATmega328P because that is the microprocessor for the Uno)<b>: Tools\Board\Arduino Uno</b>.
<li>Select the Arduino as ISP as the programmer<b>: Tools\Programmer\Arduino as ISP</b>.
<li>Install the bootloader<b>: Tools\Burn Bootloader</b>.
</ol>
<div style="margin-bottom: 0.1in;">That's all there is to it. It takes less than a minute for the process to complete. Once the TX and RX LEDs, on the Arduino, stop blinking, the bootloader is loaded. </div>
<h3>Uploading Sketch Via FTDI</h3>
<div style="margin-bottom: 0.1in;">Once the boatloader is installed, you can upload a sketch to the jig using the FTDI Basic board. When I plugged my FTDI Basic into my USB port, for the first time, I found that the drivers had already been installed on my Windows 8.1 system. They must have been part of the Arduino IDE installation. If you do not have the drivers, check out Sparkfun's product page for instructions on getting them. The FTDI Basic costs about $15 at Sparkfun. </div>
<h3>Raspberry Pi/Gertboard</h3>
<div style="margin-bottom: 0.1in;">The Gertboard is a expansion board that connects to the Raspberry Pi's GPIO pins. It has several different circuits useful for interfacing the Raspberry Pi to the outside world. The Gertboard works with all thee versions of the Raspberry Pi (A, B, B+). Here is what the Gertboard offers<b>:</b></div>
<ul>
<li>ULN2808 containing six open collector outputs, each capable of driving a 500ma. load up to 50V (from a separate power source)
<li>MCP4802 dual channel D>A (digital to analog) converter
<li>MCP3002 dual channel A>D (analog to digital) converter
<li>ROHM BD6222HFP H bridge motor controller (need a separate power source)
<li>12 output buffer circuits
<li>12 input buffer circuits
<li>12 red LEDs
<li>3 momentary switches
<li>ATmega328P microcontroller. Running on 3.3V with a 12MHz resonator. All IO pins are available.
</ul>
<div style="margin-bottom: 0.1in;">The documentation, unbelievably not provided when you purchase the product, is excellent. <a href="http://www.element14.com/community/servlet/JiveServlet/previewBody/51727-102-1-265829/Gertboard_UM_with_python.pdf">It can be found here.</a> The manual references C and python programs that can be used to test out each section of the Gertboard. In order to use the ATmega328P, a bit of software must be loaded in the Raspberry Pi. This is also referenced in the manual and is available from Gordon Henderson. <a href="https://projects.drogon.net/raspberry-pi/gertboard/">Here is a link to his blog.</a> It all just works great. Newark Element14 has the Gertboard for $40. Inexplicably, Sparkfun sells it for $60. On Sparkfun's product page it lists the microcontroller as an ATmega328. It's an ATmega328P.</div>
<div style="margin-bottom: 0.1in;">My jig will look to the Raspberry Pi just like the ARmega328P on the Gertboard. Therefore, if you want to interface an ATmega328P to a Raspberry Pi without using the Gertboard, the same software from Gordon will do the job. Just make the connections as in the diagram above. </div>
<div style="margin-bottom: 0.1in;">Once you upload a sketch, you may need to communicate with the ATmega328P, such as you do with an Arduino. For the Arduino, you use the Serial Monitor function of the Arduyino IDE. You will not be able to do that from the Raspberry Pi, but you can still communicate with the ATmega328P. You connect RX and TX on the FTDI side of the jig to TX and RX, respectively, on the Raspberry Pi. You connect the FTDI TX to pin 10 (RX) of the Pi and FTDI RX to pin 8 (TX) of the Pi. The alternative to the Serial Monitor is to use a terminal program like minicom within a terminal window on the Raspberry Pi. The installation and use of the minicom program is covered in the Gertboard User's Manual.</div>
<h3>Going On From Here</h3>
<div style="margin-bottom: 0.1in;">Obviously, the jig as it stands, does not have much utility as it only uses one of the many ATmega328P's IO pins. However, the concept can be used to make something more useful. Here is an example of a project in the works: </div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi50TJBgYLImc6QXhxmCAZ52FlKpTpeNx4yLaVOUIECZqmaxB6w36W0zgbQzgKidlXl-nkwOAKzkG1QKnwoFriCRK9WX2LiZwVc_hyr4OIDnuQ7hQTN_gqu7Ylauh3V-JJ1xm8U3fv_iH_O/s1600/Next+step.jpg" imageanchor="1" style="float:left; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi50TJBgYLImc6QXhxmCAZ52FlKpTpeNx4yLaVOUIECZqmaxB6w36W0zgbQzgKidlXl-nkwOAKzkG1QKnwoFriCRK9WX2LiZwVc_hyr4OIDnuQ7hQTN_gqu7Ylauh3V-JJ1xm8U3fv_iH_O/s300/Next+step.jpg" /></a>
<div style="margin-bottom: 0.1in;">All of this goes into an enclosure. I will add temperature sensors and a RF transmitter, with antenna. The ATmega328P is mounted in a standard 28 pin socket instead of the Zif socket. A 16MHz crystal provides the clock reference.</div>
<div style="margin-bottom: 0.1in;">Note the FTDI basic board. It's used to communicate with the ATmega328P. This is necessary to tell the LCD what text to display. Once power is applied, the display is blank. I attach the FTDI Basic board, connect it to the PC, via a USB cable, and bring up the Arduino IDE. The sketch is already running on the ATmega328P so I click on the Serial Monitor and am greeted with a request to type a message. Once that is done, the message is displayed in a Time Square Scroll. I can then remove the FTDI Basic board. </div>
<div style="margin-bottom: 0.1in;">Please check out my blog entries of March 7, 2013 to April 18, 2013 for discussions of my LCD projects for the Raspberry Pi. The last two posts, specifically, are about my Times Square Scroll software. I have since converted the software from python to C to run on the Arduino. I'll report on that effort at a later time.</div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-36328542445070291122014-10-20T23:36:00.003-04:002014-10-22T18:37:30.745-04:00DS18B20 12 Bit Resolution - What does that mean<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<h3>DS18B20 Resolution</h3>
<div style="margin-bottom: 0.1in;">The following is from figure 2 of the Maxim Integrated data sheet: "DS18B20 Programmable Resolution 1-Wire Digital Thermometer"</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVbdL6Euhic8xNAFtQLe3dtC88Ah_MGIjovkU_NCzDao8NKRlm07Di7DfBlhtUcQatzvO8Q561gDrakyET3MlKIbzDmlzK_dvR2Lc0fPHr-75xNyJIRaUxQ3iph7ijCbyqAuWznz3bw6vi/s1600/TemperatureRegister.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVbdL6Euhic8xNAFtQLe3dtC88Ah_MGIjovkU_NCzDao8NKRlm07Di7DfBlhtUcQatzvO8Q561gDrakyET3MlKIbzDmlzK_dvR2Lc0fPHr-75xNyJIRaUxQ3iph7ijCbyqAuWznz3bw6vi/s590/TemperatureRegister.JPG" /><div class = "caption"><i>Temperature Register Format</i></div></a></div>
<div style="margin-bottom: 0.1in;">When the data sheet talks about 12 bit resolution, what do they mean? From the figure above, you can see that two 8 bit bytes are reserved for the temperature measurement. That means there are a total of 16 bits. But, notice there are only 12 unique bits. Bits 11 to 15, of the most significant byte (MS Byte), will always be the same. If one bit is a "1", all 5 bits will be a "1". If one bit is a "0", all 5 bits will be a "0". That is where the 12 comes from<b>:</b> 12 unique bits. </div>
<div style="margin-bottom: 0.1in;">How is that number related to resolution? Of those 12 bits, eight are reserved for the integer part of the number<b>:</b> bit 4 to bit 11. Bit 0, bit 1, bit 2, and bit 3 make up the fractional component. You can choose to have the DS18B20 measure with 9, 10, 11, or 12 bit resolution. If you choose 12 bits, all 12 bits are used in the calculation of temperature. If you choose 11 bits, the least significant bit will always be a 0. If you choose 10 bits, the last two bits will always be zero. If you choose nine bits, the last three bits will always be zero giving you only one fractional bit of resolution. </div>
<div style="margin-bottom: 0.1in;">With nine bits, the least significant bit is bit 3. The value of bit 3 (from the figure above) is 2<sup>-1</sup>. That is the equivalent to <sup>1</sup>⁄<sub>2</sub> or 0.5. So, nine bits gives you a resolution of 0.5°C.</sub>. If you choose 12 bit resolution, the least significant bit has a value of 2<sup>-4</sup>. That gives you a resolution of <sup>1</sup>⁄<sub>16</sub> or 0.0625. So, 12 bits gives you a resolution of 0.0625°C.</sub>. </div>
<div style="margin-bottom: 0.1in;">Why would you want to choose anything other than 12 bit resolution? Why not always choose the best? The answer is speed. When asked for a temperature conversion, the DS18B20 takes multiple measurements and averages them before reporting the result. The higher the resolution, the larger the number of measurements go into the average, and the longer time to complete the conversion. The maximum conversion time for 12 bit resolution is eight times the maximum time for nine bit resolution. Here is a chart of resolution in bits, degrees, and maximum conversion time:</div>
<table style ="margin-bottom: 0.1in;">
<tr>
<td width = "100px" style="text-align: center;"><b>Number of Bits</b></td>
<td width = "100px" style="text-align: center;"><b>Resolution </b></td>
<td width = "200px" style="text-align: center;"><b>Maximum Conversion Time, ms.</b></td>
</tr>
<tr>
<td width = "100px" style="text-align: center;">9</td>
<td width = "100px" style="text-align: center;">0.5000°C</td>
<td width = "200px" style="text-align: center;">93.75</td>
</tr>
<tr>
<td width = "100px" style="text-align: center;">10</td>
<td width = "100px" style="text-align: center;">0.2500°C</td>
<td width = "200px" style="text-align: center;">187.5</td>
</tr>
<tr>
<td width = "100px" style="text-align: center;">11</td>
<td width = "100px" style="text-align: center;">0.1250°C</td>
<td width = "200px" style="text-align: center;">375</td>
</tr>
<tr>
<td width = "100px" style="text-align: center;">12</td>
<td width = "100px" style="text-align: center;">0.0625°C</td>
<td width = "200px" style="text-align: center;">750</td>
<tr>
</tr></table>
<h3>Deriving Temperature From the Register Data - Temperatures below 0°C</h3>
<div style="margin-bottom: 0.1in;">The following is Figure 1 from the Maxim data sheet<b>:</b></div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz3rAF_k_1pQzTWIqcuLHQBp7CyRymnXZC9_l5Z_c_B14MMFqcfIe78ZfrmrIc0vSqDwoHrC4nbHtR7gDYggzbEePWoebEbN0Rq-Rs_8jm19plOs9fJH8KhdsX6_FxW7_V0IXJnHmCHjhJ/s1600/TemperatureDataRelationship.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz3rAF_k_1pQzTWIqcuLHQBp7CyRymnXZC9_l5Z_c_B14MMFqcfIe78ZfrmrIc0vSqDwoHrC4nbHtR7gDYggzbEePWoebEbN0Rq-Rs_8jm19plOs9fJH8KhdsX6_FxW7_V0IXJnHmCHjhJ/s540/TemperatureDataRelationship.JPG" /><div class = "caption"><i>Temperature/Data Relationship</i></div></a></div></div>
<div style="margin-bottom: 0.1in;">I hope it is clear how the decimal value of temperature relates to the binary digital output column when the temperatures are in the positive range. It might not be as clear when the temperatures are negative. Those binary numbers are really <i>signed</i> binary numbers. This means that the most significant bit, bit 11, or in this case, bits 11 through bit 15 (since these five bits are always the same), tell you if the number is positive or negative. If those bits are all "0"'s the number is positive. If those bits are all "1"'s the number is negative. However, that is only half the story. You might think that if +25.0625 is 0000 0001 1001 0001 then -25.0625 could be 1111 1001 1001 0001. But you see from the figure above that is not the case. </div>
<div style="margin-bottom: 0.1in;">As small as the DS18B20 is, it has to have some computing power. Therefore, it shares characteristics with your microprocessor or microcontroller device. These devices all have some electronic circuitry that perform basic functions. One such function is to add binary numbers. Another is to change all the "1"'s to "0"'s and all the "0"'s to "1"'s. That operation is called inverting. A function that is not commonly implemented is circuitry to perform subtraction. That is because it is possible to subtract by using the two circuits I described, adding and inverting. </div>
<div style="margin-bottom: 0.1in;">How would you subtract 13 from 25 without actually performing subtraction. Let's assume we were working with 8 bit signed binary numbers. 25 is 0001 1001. 13 is 0000 1101. Subtracting 13 from 25 is the same as adding -13 to +25. In order to facilitate the subtraction process, devices like the DS18B20 (because they must do some computing) represent negative numbers by what is called the two's complement of the number. The two's complement is formed by using the aforementioned processes, adding and inverting. First we invert then we add 1.</div>
<div style="margin-bottom: 0.1in;">Let's get the two's complement of -13. First, we invert the 0000 1101 to get 1111 0010. Next, we add 1 yielding 1111 0011. When we add that to 0001 1001 (25) we get 1 0000 1100. Since we are using 8 bit signed binary numbers, that lonely "1" on the left gets lost giving us our final result of 0000 1100 which is decimal 12. This is how the DS18B20 represents the binary (and hex) temperatures that are below 0°C<b>:</b> by their two's complement. Let's prove it. If +25.0625 is 0000 0001 1001 0001. What is -25,0625 in two's complement? Let's invert 0000 0001 1001 0001 to 1111 1110 0110 1110 and add 1. This gives us 1111 1110 0110 1111, which is what is shown in the figure above.</div>
<div style="margin-bottom: 0.1in;">If you want more information on two's complement, including some theory,<a href="http://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html"> I recommend this site.</a> </div>
<h3>Calculating Temperature From DS18B20 Register Values</h3>
<div style="margin-bottom: 0.1in;">When you get the results from the DS18B20, two bytes from the scratchpad, how do you convert them to temperature? Without getting theoretical, this is what I do:</div>
<ol>
<li>Multiply the value of the most significant byte (scratchpad byte 1) of the temperature data by 256.
<li>Add to the result of step 1, the the value of the least significant byte (scratchpad byte 0).
<li>Check to see if the temperature is negative by testing if the result from step 2 is over 127. If so the temperature is negative.
<li>If the temperature is negative, subtract the result of step 2 from 65536.
<li>Divide by 16
</ol>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-72332740445672596492014-07-13T11:51:00.000-04:002015-03-31T16:58:58.268-04:00Cyclic Redundancy Check (CRC) of DS18B20 Serial Data<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;"><b>This is a continuation of my last three blog posts.</b></div>
<div style="margin-bottom: 0.1in;">Maxim has application note 27, "Understanding and Using Cyclic Redundancy Checks with Maxim 1-Wire and iButton Products", that I will refer to here. <a href="http://www.maximintegrated.com/en/app-notes/index.mvp/id/27"> You can see this here.</a> </div>
<div style="margin-bottom: 0.1in;">If you transmit data from one place to another you want to know that the data arrived unchanged. The cyclic redundancy check is the best way to tell you if the transmission was successful. </div>
<div style="margin-bottom: 0.1in;">We transmit serial data from two sources within the DS18B20: from its Read Only Memory which has the ROM code stored, and from the scratchpad memory. Basically, while transferring data to us, the user, the DS18B20 looks at the data it is sending, one bit at a time, and makes a calculation. The result of that calculation is an additional byte that is tacked on to the data stream. The value of this byte depends solely on the bits that have preceded it in the transmission. This additional byte is the CRC byte. The ROM code is actually 7 bytes long but the CRC byte makes it 8 bytes long. The scratchpad data is 8 bytes long and its CRS makes it 9 bytes long. </div>
<div style="margin-bottom: 0.1in;">My code calculates the CRC as each bit of each byte is received. One of the nice things about CRC, and, this should be kept in mind, is if the transmission was successfully received, my calculation of the CRC will be 0. It's very easy to check for 0 in code. Any result besides 0 means the transmission failed.</div>
<div style="margin-bottom: 0.1in;">How do you calculate CRC? It's hard to put that into words. The mechanism for calculating CRC is generally expressed as an electronic circuit. You can actually build this circuit and calculate the CRC, or you can emulate this circuit in software. I have done the latter in my One_wire_DS18B20 library file. I was surprised how few lines of code it took to write the CRC function. More on this later. </div>
<h3 style="margin-bottom: 0.05in;">Getting Into Electronic Hardware</h3>
<div style="margin-bottom: 0.1in;">Here we go diving into interesting waters. But, I don't know how to otherwise discuss how this all works. So here we go. Maxim gives a representation of the electronic circuit in it's figure 2 of the application note. Here it is:</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1etPxWZ0kFNY1Tt_psTHztIeYdFQcS3m9EslfQErzfKPAGHStBu7x6n9kU_IApm8JmdCXDxbfdtp4i8H43SoiIaRIB57xrP-4wC1QiKzAXT6d4dgTA9pNjCPT2-iTzWomsuJDe_KGvIBa/s2160/Maxim_CRC-Circuit.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1etPxWZ0kFNY1Tt_psTHztIeYdFQcS3m9EslfQErzfKPAGHStBu7x6n9kU_IApm8JmdCXDxbfdtp4i8H43SoiIaRIB57xrP-4wC1QiKzAXT6d4dgTA9pNjCPT2-iTzWomsuJDe_KGvIBa/s540/Maxim_CRC-Circuit.JPG" /><div class = "caption"><i>CRC Circuit from Maxim's Application Note 27</i></div></a></div></div>
<div style="margin-bottom: 0.1in;">I have my own version of that figure that shows more detail, especially what is in those boxes called stages: </div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyjOdjPpxS2_nmKzHkSg3BhHkqeoOKMXGods-iXz1w1UxBFK2faY_w07zncXzKJd4CQL8YOdD7aZjZtub8hG8AJ7SV9-w4nX59Kv5Zt3XUDtRL63Wszy5aWpciniKtwZtNzl8SF82rntPb/s2160/ShiftRegisterForCRC.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyjOdjPpxS2_nmKzHkSg3BhHkqeoOKMXGods-iXz1w1UxBFK2faY_w07zncXzKJd4CQL8YOdD7aZjZtub8hG8AJ7SV9-w4nX59Kv5Zt3XUDtRL63Wszy5aWpciniKtwZtNzl8SF82rntPb/s540/ShiftRegisterForCRC.jpg" /><div class = "caption"><i>My CRC Equivalent Circuit</i></div></a></div></div>
<div style="margin-bottom: 0.1in;">There are two different kinds of parts here, the boxes are called flip-flops (No connection to the ones you wear to the beach). Let's look at a flip-flop a little more closely:</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj53ajm-TJ-nU5Pb9U0wZlcjOg14Ee8bdATNXI4wLYw6CGbCD5Cgd37WnGVik4-c0qEbsPr_qDquBC0ZQbi73dAtMC6MKf-72ixuTY-ienRvRuQ2K04q66BR6k-aFGXF41z9NWXbarAunbU/s800/One_FlipFlop.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj53ajm-TJ-nU5Pb9U0wZlcjOg14Ee8bdATNXI4wLYw6CGbCD5Cgd37WnGVik4-c0qEbsPr_qDquBC0ZQbi73dAtMC6MKf-72ixuTY-ienRvRuQ2K04q66BR6k-aFGXF41z9NWXbarAunbU/s320/One_FlipFlop.jpg" /><div class = "caption"><i>Single D Flip-Flop</i></div></a></div>
<div style="margin-bottom: 0.1in;">Why the funny name, flip-flop? The name describes the functionality, perfectly. The output from the part can be made to flip from one state to another. That is, from a high voltage to a low voltage; or, stated another way, from a logic HIGH state to a logic LOW state; or, stated yet another way, from a "1" to a "0". Of course going back in the other direction is just as easy. Flip-flops make up a large part of the circuitry in your computer microprocessor. There are thousands of them. The simplest can be constructed with just two transistors. The flip-flip we are showing here is a bit more complex and is called a D flip-flop. Below the flip-flop, is a timing diagram that plots voltage (vertical) against time (horizontal). When the voltage is at it's high state we call this a logic "1". When the voltage is near 0 volts, we call this a "0". (That is arbitrary, we could call a high voltage a "0" and a low voltage a "1"). </div>
<div style="margin-bottom: 0.1in;">We see three signals, or waveforms: "Data", "Clock", and "Output" (we are going to ignore reset). "Data" is the information that is being transmitted serially, one bit at a time. "Clock" is another signal, and when it makes a transition from a "0" to a "1", the logic level the device sees on its "D" pin, will appear at its "Q" pin. We show that the data on the "D" pin is "latched" on the rising edge of "Clock" by those upward arrows on the "Clock" waveform. The first time we see "Clock" going from a low to a high, the "Data" happens to be high (or a "1"). After a really short delay, that "1" appears at the output of the flip-flop. That little delay is important. It is not obvious why here, but will be when we consider more than one flip-flop. If you look at each rising transition you will see the output will mirror what is at the "D" pin. So far, not so interesting. But. wait, let's connect a second flip-flop to the first one.</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSFALELFf03VdOSkx23yt2FCtfff_AEqmBojp4WqGIZr2SMuC2mG_zem6iMF0F7XhifEZxeD2uM78Blk15i8-y9yguM1I2RCLoxGNuWFKDFlw9vm7RTwsRnBo3yXOZGltt5pBTS8rL974s/s1280/Two_FlipFlops2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSFALELFf03VdOSkx23yt2FCtfff_AEqmBojp4WqGIZr2SMuC2mG_zem6iMF0F7XhifEZxeD2uM78Blk15i8-y9yguM1I2RCLoxGNuWFKDFlw9vm7RTwsRnBo3yXOZGltt5pBTS8rL974s/s320/Two_FlipFlops2.jpg" /><div class = "caption"><i>Two Flip-Flops In Series</i></div></a></div></div>
<div style="margin-bottom: 0.1in;">We connect a second D flip-flop so that its "D" ("D" for data, by the way) pin connects to "Q" of the first one. "Clock" connects to both flip-flops. Now we can see why that little delay is important. When we look at the second time the "Clock" goes from low to high, we see that the "D" pin of the first flip-flop is low, so the output of the first flip-flop wants to go low to follow the input. However, there is a slight delay so it stays high for a little while longer. If that delay was not there, the output of the first flip-flop would be changing at the exact time that "Clock" is latching the data at the input of the second flip-flop. What would the output of the second flip-flop be? A "1" or a "0"? Who knows! That little set-up delay assures that the input of the second flip-flop is a "1" long enough so the "Clock" latches a "1" at the output of the second flip-flop.</div>
<div style="margin-bottom: 0.1in;">Is this circuit any more useful than the first? The usefulness of the circuit will be evident if we add more flip-flops. Let's have a total of 8: </div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4-BMKFxhYJiYJO0fnTNz1kfYkUiRRnibKkRj3ycKiER7SpTG5t0RoUzTh5cFDnQhjri43gX9JT5n2UIhlmh1UGrtcz3EqA7SxeBsL_j8ha-UJH0YqWV93btVn8XM6AA3wnU-hxT7GDakQ/s2160/ShiftRegister2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4-BMKFxhYJiYJO0fnTNz1kfYkUiRRnibKkRj3ycKiER7SpTG5t0RoUzTh5cFDnQhjri43gX9JT5n2UIhlmh1UGrtcz3EqA7SxeBsL_j8ha-UJH0YqWV93btVn8XM6AA3wnU-hxT7GDakQ/s540/ShiftRegister2.jpg" /></a></div></div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0wEgToBCwZCKOm8BdMjwjgDWwIA8RRH4UfvrN_PTCGIY-DBodSuEEP3B2UVaBNjAycoJmXgjt3H_CaN-R1rCkc4RNHtwFpnvnTDPoe-6Mi_Z3QUtdpa3fCSkegZwq9gKBfEwzYrIhF5w4/s1600/ShiftRegister-Waveforms.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0wEgToBCwZCKOm8BdMjwjgDWwIA8RRH4UfvrN_PTCGIY-DBodSuEEP3B2UVaBNjAycoJmXgjt3H_CaN-R1rCkc4RNHtwFpnvnTDPoe-6Mi_Z3QUtdpa3fCSkegZwq9gKBfEwzYrIhF5w4/s400/ShiftRegister-Waveforms.jpg" /><div class = "caption"><i>Eight Bit Shift Register And Waveforms</i></div></a></div></div>
<div style="margin-bottom: 0.1in;">Remember, "Data" is the information coming into the circuit one bit at a time. "Clock" captures that information in the first flit-flop. As new bits arrive, they cascade to the other flip-flops from left to right. Each rising edge of "Clock" shifts the information on "Data" from flip-flop to flip-flop. Thus, this circuit is called a shift register. The flip-flop outputs are labeled "Q7" - "Q0". </div>
<div style="margin-bottom: 0.1in;">The circuit is also called a serial to parallel converter. After shifting in the serial data enough times to get the first bit cascaded down to the last flip-flop, the original eight bit data word is available on "Q7" - "Q0" in parallel format. We could connect "Q7" - "Q0" to other circuitry if we wished.</div>
<div style="margin-bottom: 0.1in;">Why the grayed out areas? We don't have enough information to know if the logic levels in these areas are a "1" or a "0". </div>
<div style="margin-bottom: 0.1in;"><b>My project emulates the shift register in software.</b> Every time we ask for data from the DS18B20, we call on a couple of functions in my 1_Wire library. We emulate "clock" with a "for" loop to shift in each bit of each byte. The "Q7" - "Q0" outputs are represented by an eight bit variable. We call that loop enough times to capture each byte in the message from the DS18B20.</div>
<div style="margin-bottom: 0.1in;"><b>As we shift in each bit, we do a calculation to determine the CRC value. </b>We continue that calculation until the last bit of the last byte of the message has been shifted in from the DS18B20. For example, if we were capturing ROM code, we would capture eight bytes. The last byte of the ROM code is the CRC value (calculated by Maxim). After shifting in all 64 bits, the result of our calculation should be "00000000" (Recall my forth paragraph above).</div>
<h3 style="margin-bottom: 0.05in;">Enough Background - Getting To The Cyclic Redundancy Check</h3>
<div style="margin-bottom: 0.1in;">Let's repeat that figure at the top of this post:</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyjOdjPpxS2_nmKzHkSg3BhHkqeoOKMXGods-iXz1w1UxBFK2faY_w07zncXzKJd4CQL8YOdD7aZjZtub8hG8AJ7SV9-w4nX59Kv5Zt3XUDtRL63Wszy5aWpciniKtwZtNzl8SF82rntPb/s2160/ShiftRegisterForCRC.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyjOdjPpxS2_nmKzHkSg3BhHkqeoOKMXGods-iXz1w1UxBFK2faY_w07zncXzKJd4CQL8YOdD7aZjZtub8hG8AJ7SV9-w4nX59Kv5Zt3XUDtRL63Wszy5aWpciniKtwZtNzl8SF82rntPb/s540/ShiftRegisterForCRC.jpg" /><div class = "caption"><i>CRC Equivalent Circuit</i></div></a></div></div>
<div style="margin-bottom: 0.1in;">Notice that this is similar to the shift register above. We have added three parts called exclusive OR gates. They each have two inputs on the left and one output on the right. The exclusive OR is one of a series of logic circuits. Some of the others are inverters (also called NOT gates), AND gates, and OR gates. These devices look at the logic levels at their inputs ("1" or "0") and decide what the logic level of their output will be. The output of the inverter is opposite of the input. The output of the AND gate is "0" unless all the inputs are "1". The output of the OR gate is a "1" if any of it's inputs are "1". The output of the exclusive OR gate will be "0" if the logic level of the inputs are the same (both "0" or both "1"). If the inputs are different ("0", "1" or "1", "0") the output will be a "1". </div>
<div style="margin-bottom: 0.1in;">That CRC circuit seems to be a bastardized version of the shift register. The output from the last stage is fed back into the circuit. This circuit is specific to the way Maxim handles the CRC for devices that transfer data in eight bit bytes. They have a different circuit for devices that transfer 16 bit bytes. That circuit has 16 "stages" </div>
<div style="margin-bottom: 0.1in;">The type of CRC circuit is also know by its polynomial, a mathematical expression representing the number of stages, and where, and, how many exclusive ORs are in the circuit. The polynomial for our circuit is shown on the figure above from Maxim's application. It is X<sup>8</sup> + X<sup>5</sup> + X<sup>4</sup> + 1. This means we take the output of the forth, fifth, and eighth stage as inputs to our exclusive OR gates. There are other schemes with different number of exclusive OR gates that feedback to different stages. These have different polynomials. </div>
<div style="margin-bottom: 0.1in;">The mathematics of the cycle redundancy check is quite involved and I won't begin to discuss it here. There is plenty of in-depth information on the web. Let's move on to the final discussion of implementing the CRC in software.</div>
<h3 style="margin-bottom: 0.05in;">Calculating the CRC in Software and in Our Equivalent Circuit</h3>
<div style="margin-bottom: 0.1in;">The following code is taken from my calculateCRC_byte function found in my One-Wire_DS18B20 library. </div>
<script src="https://gist.github.com/RaspPiGuy/b0b543dcfd404f37f42b.js"></script>
<div style="margin-bottom: 0.1in;">The Equivalent CRC Circuit diagram contains the value of the CRC in the <b>eight</b> bits of "Q7" - "Q0". Note, however, the sketch variable "CRC" is an int, not a byte, making it 16 bits long. The reason "CRC" is 16 bits long is due to lines 11 and 14 of the sketch. On those lines, "CRC" is operated upon by a value that is nine bits long. Hence, "CRC" must be longer than 8 bits. When we reach the bottom of the function, the top eight bits of "CRC" will always be "00000000". The lower eight bits will be equivalent to "Q7" - "Q0" in the circuit. The top eight bits will also be "00000000" when we arrive at the "IF" statement in line 10. </div>
<div style="margin-bottom: 0.1in;">The sketch has two loops, an outer loop for the number of bytes we send to the function, and an inner loop that runs eight times, once for each bit of the incoming byte, "inByte[i]". </div>
<h3 style="margin-bottom: 0.05in;">Lines 9 Through 15 of the Code</h3>
<div style="margin-bottom: 0.1in;">Comparing the equivalent circuit to the sketch, the "IF" statement in line 10 implements, exactly, the exclusive OR gate on the left of the equivalent circuit. Let's look at that statement closely<b>:</b></div>
<div style="margin-bottom: 0.1in;"><b><center>"if ((CRC % 2) ^ (inByte[i] % 2)){"</center></b></div>
<div style="margin-bottom: 0.1in;">The "%" operator is called a modulo. The result of the modulo operation is the remainder after dividing whatever is to the left of the operator by whatever is to the right of the operator. In this case, we divide the current value of the variable "CRC" by 2. If the value of the variable "CRC" is even, the modulo will be "0". If odd, the module will be "1". Whether or not "CRC" is even or odd depends solely upon the value of its least significant bit (last bit on the right). Therefore, the value of "CRC % 2" is the value of the least significant bit of "CRC". </div>
<div style="margin-bottom: 0.1in;">The CRC Equivalent Circuit holds the value of the CRC on its outputs "Q7" - "Q0". Applying the same argument as in the last paragraph, "CRC % 2" is the value of "Q0", the least significant bit of the CRC stored in the flip-flops.</div>
<div style="margin-bottom: 0.1in;">Using what we learned above, "inByte[i] % 2", will give us the value of the least significant bit of the data byte, "inByte[i]". This is exactly the same as the current value of "Data" in the CRC Equivalent Circuit. </div>
<div style="margin-bottom: 0.1in;">The symbol "^", in the "IF" statement, sitting between the two modulo expressions, is the bitwise exclusive OR operator. Because, "Q0" and "Data" connect to the exclusive OR at the left of the equivalent circuit, <b>the entire "IF" statement is equivalent to that same exclusive OR gate</b>. The result of the "IF" statement is precisely the same as the output of the left-hand exclusive OR gate. From our discussion of how the exclusive OR works, if the value of the least significant bit of the variable "CRC" and the value of the least significant bit of the array "inByte[i]" are the same (both "0" or both "1"), the result of the "IF" statement will be "0", otherwise (one is a "0" and the other a "1") the result will be a "1". In the same manner, if the value of "Q0" and the value of "Data" are the same, the output of the exclusive OR gate in the equivalent circuit will be "0". If different, the value will be "1". This output is the input to the first flip-flop at the left of the circuit, and one of the inputs of the other two exclusive OR gates in the equivalent circuit. </div>
<div style="margin-bottom: 0.1in;">We described of the exclusive OR gate as being a "0" if its inputs were the same and a "1" if they were different. We used that description to evaluate the "IF" statement and the output of the exclusive OR at the left of the equivalent circuit. There is another useful way to look at an exclusive OR gate, and we will use that way in the following discussion. We can look at one input of an exclusive OR as a control input that controls the relationship between the second input and the output of the gate. If this control input is a "0", the output of the exclusive OR will follow the other input. If the control is a "1", the output will be opposite of the input (A "0" becomes a "1" and a "1" becomes a "0"). </div>
<div style="margin-bottom: 0.1in;">The result of the "IF" statement controls which of the two operations we apply to the value of "CRC" (either line 11 or line 14). We either exclusive OR "CRC" with "100011000" or "000000000". In our new way to look at the exclusive OR gate, those two series of nine bits are the control inputs to nine exclusive OR gates. They control what happens to value of the variable "CRC" at that point in the sketch. We can call them a control word.</div>
<div style="margin-bottom: 0.1in;">Let's operate on a sample byte to see what those control bits do<b>:</b></div>
<table style ="margin-bottom: 0in;">
<tr>
<td width = "100px" style="text-align: center;">011010101</td>
<td width = "100px" style="text-align: center;">Sample</td>
<td width = "100px" style="text-align: center;">011010101</td>
</tr>
<td width = "100px" style="text-align: center;"><u>000000000</u></td>
<td width = "100px" style="text-align: center;">Control Word</td>
<td width = "100px" style="text-align: center;"><u>100011000</u></td>
</tr>
<td width = "100px" style="text-align: center;">011010101</td>
<td width = "100px" style="text-align: center;">Result</td>
<td width = "100px" style="text-align: center;">111001101</td>
</tr>
</table>
<div style="margin-bottom: 0.1in;">Note that when the control word is "000000000", there is no change to the sample, the result is the same as the sample.</div>
<div style="margin-bottom: 0.1in;">I said the nine bit control word was like having nine exclusive ORs. But, six of those bits are always "0", both in line 11 and line 14. Consequently, we can replace those six exclusive ORs with direct connections, meaning there are only three exclusive ORs. This happens to be the same number of exclusive OR gates in our equivalent circuit. In fact, they are in the same relative positions. The most significant bit of our control word corresponds to the left-hand exclusive OR gate. The two bits of the control word that can change, are in exactly the same place as the other two exclusive OR gates in the circuit. </div>
<div style="margin-bottom: 0.1in;">The purpose of the exclusive ORs are to modify the value of CRC existing at "Q7" - "Q0", or the value of the variable "CRC", before there is further processing. If the control word is "000000000", there will be no change in the value of "CRC". Since, the effect of exclusive ORing "CRC" with "000000000" is no effect at all, lines 13 - 15 of the sketch are superfluous. They do not appear in my actual code. I only added them here because it made explanations easier. </div>
<div style="margin-bottom: 0.1in;">Let's look at the output of our exclusive ORs, be they in the sketch or the equivalent circuit. Exclusive ORing with "000000000" was the result of the output of the "IF" statement being "0". Let's see what happens to the equivalent circuit when the output of the left-hand exclusive OR is "0". First, the input to the left-hand flip-flop will be "0". The output of the left-hand exclusive OR also connects to an input of the other two exclusive ORs. Let's consider the output of the left-hand exclusive OR to be the control input to the other two flip-flops. If this control input is "0", the output of the two flip-flops ("Q4" and "Q3") will be the same as their other inputs, meaning there will be no change to the CRC.</div>
<div style="margin-bottom: 0.1in;">When the output of the "IF" statement is "1" we will modify the value of the variable "CRC" with "100011000". At the equivalent circuit, the output of the left-hand exclusive OR will be a "1". The effect will be that the input of the left-hand flip-flop will be "1" and the control input to the other two exclusive ORs will be a "1". This will cause the "X4" to be of the opposite logic level of "Q4" and "X3" to be of the opposite logic level of "Q3". In other words, we have flipped those two bits.</div>
<h3 style="margin-bottom: 0.05in;">Lines 16 and 17 of the Code</h3>
<div style="margin-bottom: 0.1in;">"Whew", we now have the variable "CRC", and the inputs of those flip-flops, set up for the next operation. </div>
<div style="margin-bottom: 0.1in;">In the equivalent circuit, the signal labeled "Clock", which has been at "0" will briefly go to a "1" and back to "0". As in our discussion of the shift register, the logic level at the inputs of those flip-flops will now appear at the outputs of the flip-flops. This has the effect of shifting the current value of CRC down one position. Sometime after that, the value of "Data" will have the next bit of the serial data coming into the circuit.</div>
<div style="margin-bottom: 0.1in;">Our sketch has an exact equivalent to the "clock" signal. That equivalent is line 16<b>: "CRC >>= 1;"</b>. This operation will take the value of "CRC" and shift all 16 bits down one bit position to the right. A "0" will be shifted into the most significant bit of "CRC". </div>
<div style="margin-bottom: 0.1in;">The next line, line 17, shifts the eight bits of "inByte[i]"down one bit to the right. A "0" will be shifted into the most significant bit. The operations of lines 16 and 17, are directly comparable to applying the clock to the flip-flops, and introducing the next data bit, in the equivalent circuit.</div>
<h3 style="margin-bottom: 0.05in;">An Example</h3>
<div style="margin-bottom: 0.1in;">Let's take an example of two bytes and walk them through the sketch. Let's assume the two bytes are "10110100" and "01010011". If I run "10110100" through the sketch, by itself, the resulting CRC will be "0000000001010011". If we ignore the top 8 bits, the CRC is the same as the second byte we will pass to the sketch. Since the second byte is the same as the CRC of the first byte, the final CRC should be "0000000000000000", after processing both bytes. </div>
<div style="margin-bottom: 0.1in;">First Byte 1<b>:</b></div>
<table style ="margin-bottom: 0in;">
<tr>
<td width = "50px" style="text-align: center;"><b>i</b></td>
<td width = "50px" style="text-align: center;"><b>j</b></td>
<td width = "100px" style="text-align: center;"><b>inByte[i]</b></td>
<td width = "200px" style="text-align: center;"><b>CRC</b></td>
<td width = "200px" style="text-align: center;"><b>CRC Before Right Shift</b></td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">0</td>
<td width = "50px" style="text-align: center;">0</td>
<td width = "100px" style="text-align: center;">10110100</td>
<td width = "200px" style="text-align: center;">0000000000000000</td>
<td width = "200px" style="text-align: center;">0000000000000000</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">0</td>
<td width = "50px" style="text-align: center;">1</td>
<td width = "100px" style="text-align: center;">01011010</td>
<td width = "200px" style="text-align: center;">0000000000000000</td>
<td width = "200px" style="text-align: center;">0000000000000000</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">0</td>
<td width = "50px" style="text-align: center;">2</td>
<td width = "100px" style="text-align: center;">00101101</td>
<td width = "200px" style="text-align: center;">0000000000000000</td>
<td width = "200px" style="text-align: center;">0000000100011000</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">0</td>
<td width = "50px" style="text-align: center;">3</td>
<td width = "100px" style="text-align: center;">00010110</td>
<td width = "200px" style="text-align: center;">0000000010001100</td>
<td width = "200px" style="text-align: center;">0000000010001100</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">0</td>
<td width = "50px" style="text-align: center;">4</td>
<td width = "100px" style="text-align: center;">00001011</td>
<td width = "200px" style="text-align: center;">0000000001000110</td>
<td width = "200px" style="text-align: center;">0000000101011110</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">0</td>
<td width = "50px" style="text-align: center;">5</td>
<td width = "100px" style="text-align: center;">00000101</td>
<td width = "200px" style="text-align: center;">0000000010101111</td>
<td width = "200px" style="text-align: center;">0000000010101111</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">0</td>
<td width = "50px" style="text-align: center;">6</td>
<td width = "100px" style="text-align: center;">00000010</td>
<td width = "200px" style="text-align: center;">0000000001010111</td>
<td width = "200px" style="text-align: center;">0000000101001111</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">0</td>
<td width = "50px" style="text-align: center;">7</td>
<td width = "100px" style="text-align: center;">00000001</td>
<td width = "200px" style="text-align: center;">0000000010100111</td>
<td width = "200px" style="text-align: center;">0000000010100111</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">0</td>
<td width = "50px" style="text-align: center;">7</td>
<td width = "100px" style="text-align: center;">00000000</td>
<td width = "200px" style="text-align: center;">0000000001010011</td>
<td width = "150px" style="text-align: left;"><-After the Final Shift</td>
</tr>
</table>
<div style="margin-bottom: 0.1in;">Now Byte 2<b>:</b></div>
<table style ="margin-bottom: 0in;">
<tr>
<td width = "50px" style="text-align: center;"><b>i</b></td>
<td width = "50px" style="text-align: center;"><b>j</b></td>
<td width = "100px" style="text-align: center;"><b>inByte[i]</b></td>
<td width = "200px" style="text-align: center;"><b>CRC</b></td>
<td width = "200px" style="text-align: center;"><b>CRC Before Right Shift</b></td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">1</td>
<td width = "50px" style="text-align: center;">0</td>
<td width = "100px" style="text-align: center;">01010011</td>
<td width = "200px" style="text-align: center;">0000000001010011</td>
<td width = "200px" style="text-align: center;">0000000001010011</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">1</td>
<td width = "50px" style="text-align: center;">1</td>
<td width = "100px" style="text-align: center;">00101001</td>
<td width = "200px" style="text-align: center;">0000000000101001</td>
<td width = "200px" style="text-align: center;">0000000000101001</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">1</td>
<td width = "50px" style="text-align: center;">2</td>
<td width = "100px" style="text-align: center;">00010100</td>
<td width = "200px" style="text-align: center;">0000000000010100</td>
<td width = "200px" style="text-align: center;">0000000000010100</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">1</td>
<td width = "50px" style="text-align: center;">3</td>
<td width = "100px" style="text-align: center;">00001010</td>
<td width = "200px" style="text-align: center;">0000000000001010</td>
<td width = "200px" style="text-align: center;">0000000000001010</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">1</td>
<td width = "50px" style="text-align: center;">4</td>
<td width = "100px" style="text-align: center;">00000101</td>
<td width = "200px" style="text-align: center;">0000000000000101</td>
<td width = "200px" style="text-align: center;">0000000000000101</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">1</td>
<td width = "50px" style="text-align: center;">5</td>
<td width = "100px" style="text-align: center;">00000010</td>
<td width = "200px" style="text-align: center;">0000000000000010</td>
<td width = "200px" style="text-align: center;">0000000000000010</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">1</td>
<td width = "50px" style="text-align: center;">6</td>
<td width = "100px" style="text-align: center;">00000001</td>
<td width = "200px" style="text-align: center;">0000000000000001</td>
<td width = "200px" style="text-align: center;">0000000000000001</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">1</td>
<td width = "50px" style="text-align: center;">7</td>
<td width = "100px" style="text-align: center;">00000000</td>
<td width = "200px" style="text-align: center;">0000000000000000</td>
<td width = "200px" style="text-align: center;">0000000000000000</td>
</tr>
<tr>
<td width = "50px" style="text-align: center;">1</td>
<td width = "50px" style="text-align: center;">7</td>
<td width = "100px" style="text-align: center;">00000000</td>
<td width = "200px" style="text-align: center;">0000000000000000</td>
<td width = "150px" style="text-align: left;"><-After the Final Shift</td>
</tr>
</table>
<div style="margin-bottom: 0.1in;">The DS18B20 transmits data least significant bit first. If you had an application that transmits most bit significant first you would have to modify the "IF" statement. Assuming the data coming in is 8 bits in length, you could replace "inByte[i] % 2", with "inByte[i] > 127". Also, "inByte[i] >>= 1" would be replaced with "inByte[i] <<= 1". If the CRC is calculated using a different polynomial, you would have to modify line 11 accordingly.</div>
<div style="margin-bottom: 0.1in;">Feel free to download and experiment with this sketch. You can enter as many bytes as you wish. Just add some print statements and setup() and loop() to feed the function.</div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com3tag:blogger.com,1999:blog-7443803799514447902.post-46710968891182215862014-07-07T11:32:00.000-04:002014-07-07T11:32:45.122-04:00DS18B20 Connected Using Parasitic Power<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;"><b>This is a continuation of my last two blog posts.</b></div>
<h3 style="margin-bottom: 0.05in;">Parasitic Power and 1-Wire Devices</h3>
<div style="margin-bottom: 0.1in;">The 1-Wire devices have three pins, one for power, one for ground, and one for data. However, it is possible to connect the device without connecting to a source of power. In that case, both the ground and power pins are connected to ground. That simplifies cabling as it is only necessary to run two wires instead of three. A device connected in this matter is said to be connected using parasitic power. The device gets its power, parasitically, from the data line. And, the data line is powered through a 4.7K pull-up resistor to the power source (5V for the Arduino). That relatively high value of resistance still allows the Arduino or a DS18B20 to pull the data line to a low logic state (near ground). That arrangement is sufficient to power the device for all operations except when the device is undergoing temperature conversion and when writing from the scratchpad to the device's EEPROM (not the ATmega EEPROM). For those operations, the device may draw as much as 1.5mA. That's not a lot of current, but still more than can be supplied through that pull-up resistor. For those two operations, we connect the data line, directly, to the power source. Of course, once we do that, we can't have any other operation going on that requires a transfer of data in either direction (can't pull the data line low). </div>
<h3 style="margin-bottom: 0.05in;">Parasitic Power Control Circuit</h3>
<div style="margin-bottom: 0.1in;"> Obviously, we need a switch to control when we connect the data line to the power source. The switch I devised can be seen in the figure below:</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgecIvJb28i1sIQ-OaBEhfA_j5exol7NGMbwPg7RhLSJmIUUplsZCCf-ShvsCC94BuAvp2dy9ojmjBFV0WTDOSLisU0fAijlHkpJmxNDGQc09BxVeiDkVDBSHLMM2AWGHN2I8UI_45Xkey5/s12002/DS18B20-Connections-enh.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgecIvJb28i1sIQ-OaBEhfA_j5exol7NGMbwPg7RhLSJmIUUplsZCCf-ShvsCC94BuAvp2dy9ojmjBFV0WTDOSLisU0fAijlHkpJmxNDGQc09BxVeiDkVDBSHLMM2AWGHN2I8UI_45Xkey5/s470/DS18B20-Connections-enh.jpg" /></a></div>
<div style="margin-bottom: 0.1in;">My switch is the 2N5087 PNP transistor. Why that transistor? I just happened to have a couple. The transistor can supply about 100ma., so more than 67 parasitically connected devices could sit on the bus. <a href="https://www.sparkfun.com/products/522">Sparfun has a 2N3906</a> which should work just as well. Actually, this one will sink 200ma. If you are interested, Sparkfun has a tutorial about how transistors operate. <a href="https://learn.sparkfun.com/tutorials/transistors?utm_source=SparkFun+Customer+Newsletter&utm_campaign=6cbaecebe4-June29-july4&utm_medium=email&utm_term=0_fa5287abaf-6cbaecebe4-60744089">Look here.</a></div>
<div style="margin-bottom: 0.1in;">Once a low voltage (near 0) is applied through the 1K resistor to the base of the transistor, the transistor "turns on" making a near short circuit between the collector (connected to the power source) and the emitter (connected to the the data line). I use an Arduino pin to control the transistor (PB1 in my case). When I want the switch to be off, I program PB1 to be an input. As an input, the Arduino can not supply any current to the transistor's base-emitter junction so the transistor can not turn on. When I want the switch on, I program the logic level at PB1 to be LOW and program the pin to be an output. </div>
<h3 style="margin-bottom: 0.05in;">Detecting Devices Connected Using Parasitic Power</h3>
<div style="margin-bottom: 0.1in;">It is not necessary to keep track of the devices that are connected using parasitic power. You can use the library function command read_power_supply(). Like all function commands it must be preceded by initialization(), and either match_rom() or skip_rom(). Function match_rom() will address only one device - the one with the ROM code you pass to it. If that device is connected with parasitic power it will pull the data line low. If skip_rom() is employed, ANY device connected with parasitic power will pull the data line low. </div>
<h3 style="margin-bottom: 0.05in;">Programming Consequences of Devices Connected Using Parasitic Power</h3>
<div style="margin-bottom: 0.1in;">In my library function Convert_t(), if a device is not connected using parasitic power, I let the device inform my code when the convert operation is complete. The device will pull the data line to a logic LOW while the conversion is taking place. My library function reads the data line every millisecond. When a logic HIGH is read my code can move on and do its next operation. According to the data sheet, the resolution at 12 bits should take no more than 750ms. I found that the conversion is done in about 550ms. at 12 bit resolution. </div>
<div style="margin-bottom: 0.1in;">If using parasitic power, the device can not pull the data line low because of the hard pull-up. The only option is to pass the resolution to the convert_t() function and use a delay() statement to give the device enough time to make the conversion. To be sure enough time is given, I use the specification in the data sheet. </div>
<div style="margin-bottom: 0.1in;">You can look at my Read_Temperature.ino sketch to see more of my implementation of parasitic power. It is one of my files on GitHub, <a href="https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/blob/master/DS18B20_Temperatur_%20Sensor/Read_Temperatures/Read_Temperatures.ino">but you can see it here</a>.</div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-14739001428543977712014-07-05T11:14:00.000-04:002014-07-05T11:14:46.796-04:00My 1-Wire Arduino Library for DS18B20 Temperature Sensor<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;"><b>This is a continuation of my last blog post.</b></div>
<div style="margin-bottom: 0.1in;"></div>
<h3 style="margin-bottom: 0.05in;">The Include File For the 1-Wire DS18B20 Library</h3>
<div style="margin-bottom: 0.1in;">This 1-wire library will work equally well with an Arduino and a Gertboard. </div>
<script src="https://gist.github.com/RaspPiGuy/40ef2b19bfeb4d59b64e.js"></script>
<div style="margin-bottom: 0.1in;">At the top of the file are #define statements to account for your hardware set-up. Unless you use the same hardware choices I made, you make the appropriate changes to the file and save the file.</div>
<div style="margin-bottom: 0.1in;">The first #define is for CLOCK_FACTOR. I reported in an earlier post that the delayMicroseconds(), Arduino IDE, function is not accurate when using the Gertboard. I tested this thoroughly, at different values, using an oscilloscope. My results show that you must divide the desired delay by 0.67 to get an accurate delay. Consequently, if you use the Gertboard, make the clock_factor 0.67. Select 1.0 for the Arduino. The difference is caused by the 12MHz clock frequency of the Gertboard compared to 16MHz of the Arduino. The delay() function requires no correction.</div>
<div style="margin-bottom: 0.1in;">The rest of the #defines relate to the selection of the two Arduino data pins you select. One pin is the data pin for the 1-wire bus, and the other is the pin that controls the transistor for parasitic power. I will have a post devoted to the parasitic power transistor circuit. Hopefully, my comments, in the file, are enough to guide you through the selections.</div>
<div style="margin-bottom: 0.1in;">If you use the Gertboard you can take the pin names as they appear by the J28 connector (PB1 for example). These are the same designations as used in the ATmega's data sheet, and, more importantly, the same designation as used in the avr/io.h include file. If you use the Arduino, where pin numbers are 0 to 13, you will need to convert them to the ATmega numbers.</div>
<table style ="margin-bottom: 0.1in;">
<tr>
<td width = "72px" style="text-align: center;">Arduino</td>
<td width = "100px" style="text-align: center;">ATmega</td>
<td width = "72px" style="text-align: center;">Arduino</td>
<td width = "100px" style="text-align: center;">Atmega</td>
<td width = "72px" style="text-align: center;">Arduino</td>
<td width = "100px" style="text-align: center;">Atmega</td>
</tr>
<tr>
<td width = "72px" style="text-align: center;">0</td>
<td width = "100px" style="text-align: center;">PD0</td>
<td width = "72px" style="text-align: center;">5</td>
<td width = "100px" style="text-align: center;">PD5</td>
<td width = "72px" style="text-align: center;">10</td>
<td width = "100px" style="text-align: center;">PB2</td>
</tr>
<tr>
<td width = "72px" style="text-align: center;">1</td>
<td width = "100px" style="text-align: center;">PD1</td>
<td width = "72px" style="text-align: center;">6</td>
<td width = "100px" style="text-align: center;">PD6</td>
<td width = "72px" style="text-align: center;">11</td>
<td width = "100px" style="text-align: center;">PB3</td>
</tr>
<tr>
<td width = "72px" style="text-align: center;">2</td>
<td width = "100px" style="text-align: center;">PD2</td>
<td width = "72px" style="text-align: center;">7</td>
<td width = "100px" style="text-align: center;">PD7</td>
<td width = "72px" style="text-align: center;">12</td>
<td width = "100px" style="text-align: center;">PB4</td>
</tr>
<tr>
<td width = "72px" style="text-align: center;">3</td>
<td width = "100px" style="text-align: center;">PD3</td>
<td width = "72px" style="text-align: center;">8</td>
<td width = "100px" style="text-align: center;">PB0</td>
<td width = "72px" style="text-align: center;">13</td>
<td width = "100px" style="text-align: center;">PB5</td>
</tr>
<tr>
<td width = "72px" style="text-align: center;">4</td>
<td width = "100px" style="text-align: center;">PD4</td>
<td width = "72px" style="text-align: center;">9</td>
<td width = "100px" style="text-align: center;">PB1</td>
</tr>
</table>
<div style="margin-bottom: 0.1in;">The rest of the file declares the functions in the library source file. These are the public functions, those that can be called from a sketch, and the private functions, those that are not available from sketches. </div>
<h3 style="margin-bottom: 0.05in;">The Soruce File For the 1-Wire DS18B20 Library</h3>
<script src="https://gist.github.com/RaspPiGuy/23e3605322154e095566.js"></script>
<div style="margin-bottom: 0.1in;">Most of the functions are short. Their comments are longer than the code. You will have to be familiar with ATmega register programming and bit manipulation. <a href="http://thepiandi.blogspot.com/2014_01_01_archive.html">I have tutorial on useing direct register programming here.</a></div>
<div style="margin-bottom: 0.1in;">In the next several posts, I'll go into some detail on the search_device() and calculateCRC_byte() functions. But, first, I need to address parasitic power and what to do about it. That's next.</div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-68680713829579915362014-06-15T17:00:00.000-04:002014-07-03T15:11:56.316-04:00DS18B20 Temperature Project For Gertboard/Arduino<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;">Some time ago I became rather fascinated with the Maxim/Dallas DS18B20 temperature sensor. I bought a couple and connected them to my Pi. This blog has tracked my progress with the little device, starting with the four posts of June of 2013<b>:</b></div>
<UL>
<LI><a href="http://thepiandi.blogspot.com/2013/06/a-raspberry-pi-thermometer-hardware.html">Introduction to the hardware</a>
<LI><a href="http://thepiandi.blogspot.com/2013/06/a-raspberry-pi-thermometer-software.html">Introduction to the software</a>
<LI><a href="http://thepiandi.blogspot.com/2013/06/a-raspberry-pi-thermometer-interpreting.html">Interpreting the data</a>
<LI><a href="http://thepiandi.blogspot.com/2013/06/a-raspberry-pi-thermometer-my-software.html">Software to display the Temperature</a>
</UL>
Then, the October, 2013 post<b>:</b>
<UL>
<LI> <a href="http://thepiandi.blogspot.com/2013/10/graphing-real-temperature-data-using.html">Graphing the results of multiple devices using RRDTool</a>
</UL>
Finally, the November, 2013 addition<b>:</b>
<UL>
<LI><a href="http://thepiandi.blogspot.com/2013/11/adding-graphical-users-interface-to.html">Adding a graphical users interface using Tkinter</a>
</UL>
<div style="margin-bottom: 0.1in;">That project became very useful and I learned a lot. However, I had a couple of issues. I did not think it was suitable to tie up a general purpose microprocessor (the Pi) with a connection to a couple of sensors. I was disappointed that the driver did not support all functionality of the device like choice of resolution. There also seemed to be a stability issue. About half of the measurements resulted in a CRC failure requiring measurement repetition. </div>
<div style="margin-bottom: 0.1in;">I thought the sensors should really connect to a microcontroller like the ATmega328P. Once programmed, the microcontroller could be lifted off the programmer and placed in its own circuit board in an enclosure. I did this for my <a href="http://thepiandi.blogspot.com/2014/01/camera-remote-control-free-to-move.html">camera remote control project</a> back in January of this year. </div>
<div style="margin-bottom: 0.1in;"><b>Thus was born my concept for a very involved project.</b> Here are the design parameters I set for myself: </div>
<ol>
<li>Connect multiple sensors to an ATmega328P microcontroller.
<li>Design for a hypothetical industrial application where many DS18B20 temperature sensors may be employed.
<li>Store the 8 bit ROM code and a 12 character (max) description for up to 50 devices.
<li>Use the ATmega's 1 kbyte of EEPROM to store the ROM codes and descriptions.
<li>Use the Arduino IDE to develop the code.
<li>The "programmer" will be the Gertboard connected to the Raspberry Pi.
<li>Write my own 1-Wire interface library incorporating all of the DS18B20's functions found in its data sheet.
<li>Remove the ATmega microcontroller from the programmer and install it on a circuit board within an enclosure.
<li>Connect a 16 character by 2 line LCD display to the microcontroller to display temperature and device number.
<li>Connect several switches to the microcontroller for simple menu control.
<li>The microcontroller and the Pi to communicate wirelessly.
<li>The Pi will serve as a "front end", with a menu driven choice of operations to be carried out by the microcontroller.
<li>Temperature measurements returned by the microcontroller to be graphed by the Pi using RRDtool.
</ol>
<div style="margin-bottom: 0.1in;">I've been working on items 1 - 7.</div>
<div style="margin-bottom: 0.1in;"><b>If you are interested in this project it is important to be familiar with the DS18B20 device and the 1-Wire interface.</b> Maxim has an excellent data sheet describing the functionality, programming commands, and timing requirements. <a href="http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf">It can be found here</a>. </div>
<div style="margin-bottom: 0.1in;">I wrote my own 1-Wire library for Arduino/Gertboard. You may ask why since the Arduino IDE comes with a 1-Wire library already included. I simply wanted the challenge of doing it. I also wanted to present the library to others with code and comments that anyone can understand. However, if you use the Arduino built-in functions like pinMode(), digitalWrite(), and digitalRead() to control your microcontroller I should tell you that I do not! I use ATmega direct register programming. <a href="http://thepiandi.blogspot.com/2014_01_01_archive.html">I have tutorial at this blog entry that explains the difference and how to use direct register programming.</a> </div>
<div style="margin-bottom: 0.1in;">My 1-Wire library only covers the DS18B20 temperature device. If it covered all of the Maxim devices, I would have to purchase one of each and test that it works with my library. I'm not going to do that - I'm only interested in the temperature sensors. There are a couple of other temperatures sensors and they probably will work with my library. Actually, there does not seem, to me, to be a reason to use any of the other Maxim temperature sensors. I could not see any advantage to them. At present, my library is not quite complete. Here is the status of the functions I have completed. The names are taken from the command names in the data-sheet: </div>
<ul>
<li>Initialization - Done
<li>Search Rom - Done
<li>Read Rom - Done
<li>Match Rom - Done
<li>Skip Rom - Done
<li>Alarm Search - Done (updated July 3)
<li>Convert T - Done (updated June 18)
<li>Write Scratchpad - Done
<li>Read Scratchpad - Done
<li>Copy Scratchpad - - Done (updated June 22)
<li>Recall E<sup>2</sup> - - Done but not tested (updated June 22)
<li>Read Power Supply - - Done (updated June 22)>
<li>Compute CRC (this function is not listed as a separate command in the data sheet) - Done
</ul>
<div style="margin-bottom: 0.1in;">I have not incorporated parasitic power. This really only effects Convert T at this time. I will get to that after I sort through my supply of old parts and find a suitable transistor to pull up the bus connection to Vcc. When that occurs, I will augment Convert T to handle parasitic power. I plan to complete the four functions I have not started. <font color="red">I have incorporated parasitic power into the project as of June 18.</font></div>
<h3 style="margin-bottom: 0.05in;">A disappointment with the Gertboard and the ATmega EEPROM</h3>
<div style="margin-bottom: 0.1in;">I simply could not store data in the ATmega's EEPROM when the ATmega is installed on the Gertboard. After writing to an EEPROM address, a read of that address always resulted in reading 11111111 - which is the cleared state. I spent about a week trying various programs. <b> Nothing worked</b>. </div>
<div style="margin-bottom: 0.1in;">I explained my problem on the Classic Gertboard section of the Raspberry Pi forum. A very knowledgeable fellow from the Netherlands really tried his best to help me out. We had quite a few conversations on the forum. Gert van Loo, the developer of the Gertboard chimed in a couple of times. I really thank them for their help. Ultimately, nothing worked for me. I think the one person who could have solved the problem, Gordon Henderson of Gordon Projects, did nor respond to my email. Gordon developed the means to use the Arduino IDE with the Gertboard.</div>
<div style="margin-bottom: 0.1in;">I really wanted this EEPROM access to work so I purchased an Arduino Uno, mainly just to see if my code would work at all. I connected the Arduino to the Pi and used the same Arduino IDE as I used with the Gertboard and<b> it all just worked</b>. My guess as to why it does not work with the Gertboard is the difference in how a sketch is uploaded to the ATmega chip. With the Arduino, one selects "Upload", but with the Gertboard, "Upload Using Programmer" is used. I have a feeling that the latter clears the EEPROM (writes all 1's to all bytes) before uploading. Now, one of my design parameters has changed. <b>The project is off the Gertboard and onto the Arduino.</b> Furthermore, my Arduino is now disconnected from the Pi and connected to my Windows PC. I take advantage of the much faster environment, ease of printing, and easier access to my githup repository allowed by the PC.</div>
<div style="margin-bottom: 0.1in;">As of this time, I have the library mostly written, as I discuss above. I wrote several Arduino sketches to check out the library and make the sensors useful. Now, everything runs on the Arduino - the Raspberry Pi is not involved. I have not added the lcd device - that will be next. </div>
<h3 style="margin-bottom: 0.05in;">Github Repository - Library and Sketch Files</h3>
<div style="margin-bottom: 0.1in;">I spent about a day learning about github and created a repository for this project. <a href="https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi">The repository can be found here.</a></div>
<div style="margin-bottom: 0.1in;">The repository includes three libraries<b>:</b> </div>
<ol>
<li>EEPROM_Functions library - functions used to read from and write to the ATmega EEPROM.
<li>InputFromTerminal library - to input floating point or integer numbers from the serial monitor.
<li>One_wire_DS18B20 library - all the ROM Commands and DS18B20 Functions as called out in the DS18B20 data sheet.
</ol>
<div style="margin-bottom: 0.1in;">In the repository, the directory "DS18B20_Temperatur_Sensor" contains the sketches to read temperature, scan for new devices, and manage the devices in EEPROM, etc. They include the following individual sketches:</div>
<ul>
<li>"Read_Temperature" - Asks user what devices to run, number of measurements, and time between measurements. Function determines if devices are connected using parasitic power. Measurements are made accordingly. User has the option to print out the temperature limits as well as the resolution along with the temperature. Once the run is made, displays the average of all measurements for each device. If there were any CRC errors or initialization errors, the number of these are reported. If a device is connected using parasitic power, when the device is undergoing the convert temperature process, a transistor pulls the 1-wire data line up to Vcc. The time for this "hard pullup: is dictated by the data sheet for the resolution programmed into the device's scratchpad. For devices not connected by parasitic power, when undergoing temperature conversion, the device, itself, informs the bus when the conversion is done.
<li>"Scan_for_Alarms" - Scans the 1-wire bus to see if any device's temperature is out of limits. If so, displays that information to the user. This function must determine if the device is connected using parasitic power.
<li>"Find_New_Device" - Scans the 1-wire bus to see if any device has been added. If so, asks user for a description which is stored in ATmega EEPROM along with the ROM code. Asks user to input upper and lower temperature limits and resolution. These are stored within the device's scratchpad and the device's EEPROM
<li>Devices_On_The_Bus - Uses library search_rom() to report to the user all devices it finds on the 1-Wire bus along with their ROM codes. It also reports the result of the CRC of the ROM codes.
<li>"Devices_in_EEPROM" - Displays all devices in the EEPROM along with their descriptions.
<li>"Edit_Stored_Information" - Reports to user the ROM code, description, upper and lower temperature limits and resolution for each device on the 1-wire bus. Asks user which device to change and what to change. Changes are made accordingly, and stored.
<li>"Remove_Device_From_EEPROM" - Allows user to remove ROM code and description for any device from the ATmega EEPROM. This does not remove information from the device's scratchpad or the device's EEPROM.
</ul>
<div style="margin-bottom: 0.1in;">I had hoped to combine all of the above sketches into one sketch with a menu that allowed the user to select the functionality that each individual sketch provided. I actually created that sketch but when compiled, I found I exceeded the memory space allowed for variables. I exceeded the memory space due to the large amount of text associated with print statements. I felt these print statements are more important than a menu driven capability so I abandoned that approach. It is necessary to bring up, compile, and run each sketch individually.</div>
<div style="margin-bottom: 0.1in;">Also, at the top level of the repository there is the directory "EEPROM Sketches". Under here you will find several sketches used to manipulate data in the ATmega EEPROM. These sketches were used to assist with other code development and troubleshooting.</div>
<h3 style="margin-bottom: 0.05in;">Couple of Final Comments</h3>
<div style="margin-bottom: 0.1in;">As I said, previously, it was very common to have CRC errors when controlling these sensors from the Raspberry Pi. After making many thousands of measurements, with the Arduino controlling the sensors, I have received no initialization or CRC failures.</div>
<div style="margin-bottom: 0.1in;">Just to reiterate, everything is written for the Arduino IDE. They are in the repository in such a manner that they can be downloaded directly. The libraries will have to be placed into your Arduino\libraries directory for them to be recognized.</div>
<div style="margin-bottom: 0.1in;">My next blog entries will delve into details of some of my code.</div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com3tag:blogger.com,1999:blog-7443803799514447902.post-2814724194078644922014-05-13T17:29:00.000-04:002014-05-13T17:30:36.869-04:00Arduino Libraries - DON'T DO THAT!<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;">Don't do what? Well, lets lead up to the answer to that question.</div>
<div style="margin-bottom: 0.1in;">I wrote a fairly long library .cpp file (and, of course its .h file). It worked just fine in my sketch. But, I decided to make some changes. Not wanting to lose what I had (I knew it worked) I made copies of both the .h and .cpp files, appending "save" to the file name for each of the two files. I had four files<b>:</b> something.h, something_save.h, something.cpp, and something_save.cpp. All four files were under home/pi/sketchbook/libraries. I wanted to minimize the changes to my sketch (.ino file). Therefor, I did not want to change any of the function names in the library files. I made my changes, and compiled the sketch. The result<b>:</b> I received a list of compiler errors that went on and on and on. </div>
<div style="margin-bottom: 0.1in;">To illustrate what happened, I repeated the sequence of events with a really small, and trivial example<b>:</b> </div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh06HO39-9g1H4HOifyUPLrwS6eF6-kfyfHPJ6oXxrrqAxvbDlq6cpBdLfVuc6Km5h5LSBCu3Ozz-TWmcpctFYthWZQfHlkqZBZf1QFBy1Bl18sdLxOeqHdryezl4OTQLJdRlXqACMBy88h/s2320/dot.h_dot.cpp_cropped.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh06HO39-9g1H4HOifyUPLrwS6eF6-kfyfHPJ6oXxrrqAxvbDlq6cpBdLfVuc6Km5h5LSBCu3Ozz-TWmcpctFYthWZQfHlkqZBZf1QFBy1Bl18sdLxOeqHdryezl4OTQLJdRlXqACMBy88h/s580/dot.h_dot.cpp_cropped.png" /><div class = "caption"><i>New Files On Top, Originals On The Bottom</i></div></a></div>
<div style="margin-bottom: 0.1in;">The only differences I made were to append a "+ 1" to "c = a + b" in the original .cpp file, just to make something different, and to append "_save" and "_SAVE" to the top lines of the bottom two files. I compiled the sketch and you can see what occured<b>:</b></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDYgnYPgxduOuD8DUfrFS4zEXYUVDHGh9XKJRrpq_1i3jCYXCXFpZH8IckvDqpmKjFv_CUFcBnfex01sYGRfTBKSFk2EOPvudEdeyuIUsWDmPRcyLrgx24OhUyB5FsKO1cahCBk-dKyzSz/s1450/Sketch_cropped.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDYgnYPgxduOuD8DUfrFS4zEXYUVDHGh9XKJRrpq_1i3jCYXCXFpZH8IckvDqpmKjFv_CUFcBnfex01sYGRfTBKSFk2EOPvudEdeyuIUsWDmPRcyLrgx24OhUyB5FsKO1cahCBk-dKyzSz/s580/Sketch_cropped.jpg" /><div class = "caption"><i>Result of Compiling Sketch</i></div></a></div>
<div style="margin-bottom: 0.1in;">That's a lot of error messages for a tiny example sketch. I know it's a little hard to read the error messages because of the red text. Here is what it says:</div>
<div style="margin-bottom: 0.1in;"><font color= "blue">Mylibraries/ridicules.cpp.o: In function RIDICULES::addNumbers(int, int)':</div>
<div style="margin-bottom: 0.1in;">/home/pi/sketchbook/libraries/Mylibraries/ridicules.cpp:8 multiple definition of RIDICULES::RIDICULES()'</div>
<div style="margin-bottom: 0.1in;">Mylibraries/ridicules_.cpp.o:/home/pi/sketchbook/libraries/Mylibraries/</font><font color = "red">ridicules_save.cpp:8</font>><font color= "blue"> first defined here</font></div>
<div style="margin-bottom: 0.1in;">Those three messages are repeated three times. Please note I created a directory under home/pi/sketchbook/libraries called "Mylibraries". I stick my libraries there to separate them from the ones that came pre-installed with the IDE. </div>
<div style="margin-bottom: 0.1in;">Note what I have colored red. This is reference to my ridicules_save.cpp file. My sketch does not reference "ridicules_save". Why is "ridicules_save" part of the build? To start to understand things, I did a search for the object files (".o") referenced in the compiler errors. I knew they were not in the Mylibraries directory. Here is what I found: </div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnlhNEHONajB2BRCmpUTeIIDlRhccjtxJyI9BPzjvmL7teQWCG60Vixob0I3YPeq92ZrGDkg7QrIqTGhwbWb9rR9EY10PKQs2Ed49k9GBvnzbxTZjzYZoONsPvt3gQXeYw0PvJs1w1zseZ/s1450/BuildFiles_cropped.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnlhNEHONajB2BRCmpUTeIIDlRhccjtxJyI9BPzjvmL7teQWCG60Vixob0I3YPeq92ZrGDkg7QrIqTGhwbWb9rR9EY10PKQs2Ed49k9GBvnzbxTZjzYZoONsPvt3gQXeYw0PvJs1w1zseZ/s580/BuildFiles_cropped.jpg" /><div class = "caption"><i>The Object Files Made At Compile Time</i></div></a></div>
<div style="margin-bottom: 0.1in;">Note that <b>all</b> of these object files were created at the same time. They are all created every time you compile. </div>
<div style="margin-bottom: 0.1in;">The IDE generates an object file (with an .o extension) of <b>every</b> .cpp file it finds in Mylibraries. It also makes an object file of .cpp files not in the sketch/libraries path. These ".o" files are needed to support Arduino functionality. There are other .cpp files in the sketch/libraries path that are skipped. This includes, for example, OneWire.cpp. Perhaps these are not included because I have never compiled a sketch using them. </div>
<div style="margin-bottom: 0.1in;">I would have thought the IDE would only make an object file of the .cpp files you call for in your sketch and not all the others in your directory. But it does, so now that we know we can answer that question at the top: </div>
<div style="margin-bottom: 0.1in;"><font size ="4" color = "blue">Don't have more than one .cpp file with functions that have the same name in the libraries directory. If you need to keep copies of older versions of library files stick them in a directory outside of /home/pi/sketchbook/libraries. </font></div>
<div style="margin-bottom: 0.1in;">By the way, you can have two files with addNumber() functions, just not two RIDICULES::addNumbers functions. Make one VERY_RIDICULES::addNumbers and you will be OK.</div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com1tag:blogger.com,1999:blog-7443803799514447902.post-69268392133409228372014-03-18T11:38:00.000-04:002014-06-22T14:12:31.279-04:00Writing An Arduino Library<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;">My last post included a script for controlling the angle of rotation of a small dc servo. That script expects the user to input a floating point number from the terminal. I wanted that script to concentrate on the servo code, so to avoid encumbering the script with the process of handling the user's input, I put the input handling code into a library. Never having created a library, I wanted to learn how that is done. I read several tutorials but they all seemed rather simplistic. One of my concerns was how to pass values between the code that uses the library and the library functions themselves. I started with simple functions and built on those until I arrived at the function I needed for the servo</div>
<div style="margin-bottom: 0.1in;">When you use the Arduino "Serial.read()" function to read from your terminal, you get only one character from each call. If you need more than one character, you need successive reads and a way to put those characters together into something meaningful. You also need to know when the last character was entered and some way to deal with characters entered in error. My servo script wants the user to input positive or negative floating point numbers of indeterminate length. </div>
<div style="margin-bottom: 0.1in;"><b>Note added June 22, 2014 concerning the last paragraph. </b>If you use an Arduino instead of the Gertboard, you can use the serial monitor provided by the Arduino IDE. This serial monitor works quite differently. Rather than only returning one character for each call, it buffers your key presses and returns all of the characters when you hit "enter". In switching my next project from the Gertboard to the Arduino I had to modify the library created below to accommodate this change. See my post of June 15, 2014.</div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Final Script</h3>
<div style="margin-bottom: 0.2in;">Figure 1 below is my final script to control the servo. This is the same as in my previous post. The leading comments in that script were all about making the servo work so I removed them here. This script uses the library I wrote. You cannot see any of the details associated with inputting the floating point number. Only two lines, 2, 4, and 26 deal with the library<b>:</b></div>
<script src="https://gist.github.com/RaspPiGuy/9452765.js"></script>
<div style="margin-bottom: 0.1in;"><font color="green"><center><i>FIGURE 1<b>:</b> Final Script - Without Leading Comments</i></font></center></div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Getting Started Making A Library</h3>
<div style="margin-bottom: 0.1in;">First, you develop the code, as usual, in a script using the Arduino IDE. Identify the parts of the code that will eventually be part of your library<b>:</b> functions, commands, and variables. Make sure there is test code that thoroughly tests the soon-to-be library. Compile and upload this script to make certain it will run properly. Try to break the code by changing conditions.</div>
<div style="margin-bottom: 0.15in;">My test code is the code to control the servo. Figure 2 is my script. I call it my all inclusive script because it contains everything, in one script<b>:</b> the code to input numbers and code to control the servo:</div>
<script src="https://gist.github.com/RaspPiGuy/9044957.js"></script>
<div style="margin-bottom: 0.1in;"><font color="green"><center><i>Figure 2<b>:</b> Original All Inclusive Script - No Leading Comments</i></center></font></div>
<div style="margin-bottom: 0.1in;">Most of the code (lines 3 to 68) deals with inputting the floating point number and just a few lines with the servo control.</div>
<div style="margin-bottom: 0.1in;">The code to handle inputting the number accepts any digit, accepts a minus sign only if it is the first character, accepts one, and only one, decimal point, and accepts the backspace key to make a correction. All other characters are ignored. The function returns the floating point number to the calling code. This is not a perfect solution. I don't have a way to correct individual characters. When the backspace key is pressed, a space prints on the terminal after the last character, and the entire number must be entered from scratch. </div>
<div style="margin-bottom: 0.1in;">I think it is pretty clear how the code works so I won't dwell on the details. We have two functions "termNumb()" and "clearVars()", and several variables. "clearVars()" is only called from "termNumb(). "termNumb()" is called from the program in line 91. The variables (lines 3 - 5), one int, three floats, and three boolean are needed by both functions so are global. </div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Now We Give The Code Some Class</h3>
<div style="margin-bottom: 0.15in;">Now that the code is working and tested as thoroughly as possible, it is time to define a class. We will tie those soon-to-be library functions to that class as well as those global variables we spoke about above. This script still contains the test code for controlling the servo. Figure 3 is the new script<b>:</b></div>
<script src="https://gist.github.com/RaspPiGuy/9560810.js"></script>
<div style="margin-bottom: 0.1in;"><font color="green"><center><i>Figure 3<b>:</b> The Script With Class</i></center></font></div>
<div style="margin-bottom: 0.1in;">At the top we create a class called "TERMNUMB". A class defines a data type (like an int or float). Elements you give that class are available to use when you use this class in other code. The elements of our data type, "TERMNUMB", are three functions (or methods)<B>:</B> "TERMNUMB()", "termNumb()" and "clearVars()" and seven variables. The first two functions are declared as "Public" meaning they can be accessed by other code outside of the code that implements the class. The function "clearVars()" and the seven variables are declared as "Private" which means they are not known to code that call this class, but are seen by the functions declared in the class. There is no need for "clearVars()" to be public since it is only called from "termNumb()"
</div>
<div style="margin-bottom: 0.1in;">The functions "termNumb()" and "clearVars()" are the same as seen in the original, all inclusive, script as seen in Figure 2. "TERMNUMB() is new and is a special type of function called a constructor. Notice it has no return type and its name is exactly the same as the name of the class. The constructor is the first thing you see in the code below the class creation. </div>
<div style="margin-bottom: 0.1in;">Note the function "termNumb()" has a float return type. When called, the function will return a floating point number to the calling program. </div>
<div style="margin-bottom: 0.1in;">"TERMNUMB" class also declares seven variables and these variables, as indicated above, are declared as private. Notice these are the same variables declared in Figure 2, the all inclusive script above. I have added an underscore to the names of these variables. This differentiates them from variables that are declared within the functions themselves (like inChar). </div>
<div style="margin-bottom: 0.1in;">Now that the class is created we define the three functions referenced in the class. The first function to be defined (line 14) is the constructor introduced above. Notice, in this example, there is no code associated with this function. The purpose of this function is to create an instance of the class "TERMNUMB". The way we associate "TERMNUMB()" to our class "TERMNUMB" is to use this strange syntax "<b>::</b>". The structure "<b>::</b>" is called the scope resolution operator and it says that "TERMNUMB()" is within the scope of class "TERMNUMB". The same must be done for our two other functions. "clearVars()" in the all inclusive script (Figure 2) becomes "TERMNUMB<b>::</b>clearVars()". "termNumb()" becomes "TERMNUMB<b>::</b>termNumb()". </div>
<div style="margin-bottom: 0.1in;">The code from lines 17 through 78 define the implementation of our two functions "TERMNUMB<b>::</b>clearVars()" and "TERMNUMB<b>::</b>termNumb()". The code is nearly identical to the code in the all inclusive script (Figure 2) lines 7 - 68. The only differences are in the function names, just discussed, and the underscore attached to the names of the private variables. </div>
<div style="margin-bottom: 0.1in;">We have created a class and defined the workings of the functions in that class. Now it's time to use it in our code to control our servo. Like declaring any type of variable, such as an int or float, we declare our class. This is done in line 80. We are declaring "inFromTerm" to be of type "TERMNUMB". One of the elements in "inFromTerm" is the function "termNumb()". That is exactly what we need to get the floating point number that becomes the angle our servo is to steer to. All of the work we have done culminates in line 102. The variable "angle" will be the return value from member "termNumb()" of data type "inFromTerm". </div>
<div style="margin-bottom: 0.1in;">Make sure you compile and upload this code. Test it to make sure it works as desired.</div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Making the Library Files</h3>
<div style="margin-bottom: 0.1in;">The hard work is done. What remains is to create two files. These two files will constitute the library. Essentially, they will be cut-and-pasted from file in Figure 3 above. The first file is the header file with a .h extension. The second is the object file that has a .cpp extension.</div>
<div style="margin-bottom: 0.1in;">Unfortunately, you can not make these files from the Arduino IDE because it only allows you to save a file with an .ino extension. You will have to use one of the text editors available with your Linux distribution like nano, vi, or leafpad to create, edit, and save the two files. </div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Header File</h3>
<div style="margin-bottom: 0.1in;">Figure 4, below, is the header file<b>:</b></div>
<script src="https://gist.github.com/RaspPiGuy/9418070.js"></script>
<div style="margin-bottom: 0.1in;"><font color="green"><center><i>Figure 4<b>:</b> Header File InputNumbFromTerminal.h</i></center></font></div>
<div style="margin-bottom: 0.1in;">As you can see, lines 22 - 31, in the header file, are <b>exactly</b> the same as lines 3 - 12 in Figure 3 above. Note we have added some comments to describe how the class will function.</div>
<div style="margin-bottom: 0.1in;">Lines 17, 18, and 33 prevent "TERMNUMB" from defining multiple times and from creating duplication in the final binary file. Those lines assure that the class will only be created if it had not been created before. This is standard practice when creating header files. </div>
<div style="margin-bottom: 0.1in;">Line 20 is absolutely necessary if your object code uses any of the special Arduino functions available from the Arduino IDE. In our case, that includes "Serial.read()" and "Serial.print()". If you have a pre Arduino 1.0 IDE you would use WProgram.h instead of Arduino.h. </div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Object File</h3>
<div style="margin-bottom: 0.15in;">The object file follows<b>:</b></div>
<script src="https://gist.github.com/RaspPiGuy/9418093.js"></script>
<div style="margin-bottom: 0.1in;"><font color="green"><center><i>Figure 5<b>:</b> Object File InputNumbFromTerminal.cpp</i></center></font></div>
<div style="margin-bottom: 0.1in;">The object file,Figure 5, "InputNumbFromTerminal.cpp" is the implementation of the class "TERMNUMB". Lines 4 - 68 are <b>exactly</b> the same as lines 14 - 78 in Figure 3 above. In lines 1 and 2, we include the two header files<b>:</b> Arduino.h (WProgram.h for pre Arduino 1.0 IDE), and the header file we just created, InputNumbFromTerminal.h. </div>
<div style="margin-bottom: 0.1in;">Notice that the variables declared in lines 3 - 5 in the original, all inclusive, script (Figure 2) are not declared in the object file. Instead, these are the private variables declared in the header file. In the object file, they appear with the same names except they include the underscore as their last character. </div>
<div style="margin-bottom: 0.1in;">None of the code to control the servo can be found in either the header or object files. No test software is included. That is why the testing is done before making the library files.</div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">The Header and Object Files Are Now Created - What's Next</h3>
<div style="margin-bottom: 0.1in;">The library, consisting of the header and object files, must be placed in the correct location in your file structure. For the RaspberryPi, all user libraries must go into the "/home/pi/Sketchbook/libraries/" directory or a subdirectory of "home/pi/Sketchbook/libraries/". </div>
<div style="margin-bottom: 0.1in;">VERY IMPORTANT<b>:</b>Once your files are located within the proper directory structure, you must close your Arduino IDE and any files open in the Arduino IDE. Only then, when you reopen the Arduino IDE, can your library be accessed by other code. </div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Putting It All Together - Revisiting The Final Sketch</h3>
<div style="margin-bottom: 0.1in;">I'm going to repeat the final sketch here in Figure 6 showing how we use the library to input the floating point number. </div>
<script src="https://gist.github.com/RaspPiGuy/9452765.js"></script>
<div style="margin-bottom: 0.1in;"><font color="green"><center><i>Figure 6<b>:</b> Final Script - Without Leading Comments</i></font></center></div>
<div style="margin-bottom: 0.1in;">To access the library to input the floating point number we include the header file. This is done in line 2. Note we have declared "inFromTerm" to be of the data type "TERMNUMB". We also used "inFromTerm" in the code Figure 3. We did not have to use the same name. If we had called it something else in the final sketch we would need to match that name in line 26. </div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Quick Example Of Passing Values To A Library</h3>
<div style="margin-bottom: 0.15in;">Before I developed a library, I was not certain how you pass values to a library and how you pass a value from a library. The library above shows how the latter is done, but not the former. I have a really simple library that accepts two integers from a calling program, adds them together and prints the result to the terminal. The following are the header file, the object file, and the script using the library:</div>
<script src="https://gist.github.com/RaspPiGuy/9619960.js"></script>
<div style="margin-bottom: 0.1in;"><font color="green"><center><i>Figure 7<b>:</b> Header File</i></font></center></div>
<script src="https://gist.github.com/RaspPiGuy/9619940.js"></script>
<div style="margin-bottom: 0.1in;"><font color="green"><center><i>Figure 8<b>:</b> Object File</i></font></center>
</div>
<script src="https://gist.github.com/RaspPiGuy/9619919.js"></script>
<div style="margin-bottom: 0.1in;"><font color="green"><center><i>Figure 9<b>:</b> Script Calling The Library</i></font></center>
</div>
<div style="margin-bottom: 0.1in;">Note, unlike in the library created above, we actually have some code within the constructor REALSIMPLE<b>::</b>REALSIMPLE().</div>
<div style="margin-bottom: 0.1in;">I hope this tutorial has been helpful. </div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-56243558639483681772014-03-06T13:53:00.000-05:002016-04-03T16:36:09.292-04:00Gertboard - Pulse Width Modulation - Servo Control<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;">This is really a continuation of my last post. This post carries Pulse Width Modulation further by considering the control of a servo. </div>
<div style="margin-bottom: 0.1in;">There are two types of small servos<b>:</B> a standard type and continuous type. This post describes the standard servo. <a href="http://www.adafruit.com/products/155">This is the servo I purchased from Adafruit</a>. </div>
<div style="margin-bottom: 0.1in;">The standard servo has a shaft that rotates to a desired position and stops rotating once that position is attained. It can rotate 180°, or 90° in each direction from a neutral position. </div>
<div style="margin-bottom: 0.1in;">It has a DC motor that connects through a series of gears to the shaft of a potentiometer, a device producing a variable electrical resistance. An extension of the potentiometer shaft is the output shaft of the servo. The set of gears between the motor and the potentiometer significantly reduces the speed of the motor and significantly increases its torque. </div>
<div style="margin-bottom: 0.1in;">As the motor turns the potentiometer shaft, the resulting change in resistance produces a change in voltage. Let's call this voltage "A". Another voltage is produced that comes from translating the width of input pulses to voltage. The input pulses come from your ATmega microcontroller and represent the desired shaft position of the servo. Let's call this voltage "B". Voltages "A" and "B" are compared in a feedback circuit within the servo. As long as voltage "A" does not equal voltage "B", the feedback circuit produces a voltage to turn the motor either CW or CCW. When the motor has rotated the potentiometer to the point where the voltage "A" equals voltage "B", the control circuit stops the motor. As long as voltage "B" does not change, the output shaft will not rotate. A small servo usually can prevent a fair amount of external torque from turning the shaft. </div>
<table style ="margin-bottom: 0.1in;">
<tr>
<td width = "50%"><a href="https://www.servocity.com/assets/images/Servo_Breakdown.jpg" ><img height = "180" src="https://www.servocity.com/assets/images/Servo_Breakdown.jpg" /></a>
</td>
<td width = "50%"><a href="https://learn.adafruit.com/system/assets/assets/000/009/656/medium640/beaglebone_motor_servo.jpg?1396894807" ><img height = "180" src="https://learn.adafruit.com/system/assets/assets/000/009/656/medium640/beaglebone_motor_servo.jpg?1396894807" /></a>
</td>
</tr>
<tr>
<td style="text-align: center;"><i>Photo Found On Several Sites</i>
</td>
<td style="text-align: center;"><i>Servo As Found On Adafruit's Website</i>
</td>
</tr>
</table>
<div style="margin-bottom: 0.1in;">The other type is the continuous servo. This type turns continuously and the PWM controls the direction and speed of rotation. This may be a good alternative to a toy motor as it will be geared down for a more manageable speed range.</div>
<div style="margin-bottom: 0.1in;">The ATmega328P will produce the pulses required by the servo using its Pulse Width Modulation features. In my last post, controlling a DC motor, the pulse repetition frequency was not very critical. This is not the case with the servo. The servo <b>requires</b> a pulse repetition frequency of 50Hz. We need a pulse every 20ms. The pulse duration is also specified and is in the range of 0.5ms. to 2.5ms. All the documentation I had seen for this type of servo specified the range to be 1.0ms. to 2.0ms. My particular servo, purchased from Adafruit, did not come with a data sheet, but apparently has better resolution than the typical unit. Programming from 1.0ms. to 2.0ms. did not turn the shaft 180°. Programming from 0.5ms. to 2.5ms. (confirmed by my oscilloscope) did produce 180° of rotation. </div>
<div style="margin-bottom: 0.1in;">Forget about using the Arduino AnalogWrite() function. This function provides a fixed frequency of either 490Hz or 980Hz depending on the I/O pin. We need 50Hz. for servos.</div>
<div style="margin-bottom: 0.1in;">The discussion below describes my system with a 12MHz clock frequency, and my servo that has a 0.5ms. to 2.5ms. pulse duration range. If your system is different you will have to make the appropriate adjustments. </div>
<div style="margin-bottom: 0.1in;">The first decision we have to make is what timer/counter and prescaler value to use. The decision will be based on having adequate resolution of the angle of rotation. Since we know the frequency of pulse repetition we can rearrange the formula found in my last post. This gives us two unknowns<b>:</b> the maximum count and the prescaler value. </div>
<div style="margin-bottom: 0.0in;"><b>pulse repetition freq = clock speed / (2 * prescaler * max count)</b></div>
<div style="margin-bottom: 0.0n;">Substituting the known values<b>:</b></div>
<div style="margin-bottom: 0.0in;"><b>50 = 12,000,000 / (2 * prescaler * max count)</b></div>
<div style="margin-bottom: 0.0in;">Rearranging and simplifying<b>:</b></div>
<div style="margin-bottom: 0.1in;"><b>max count = 120,000 / prescaler</b></div>
<div style="margin-bottom: 0.1in;">The range in pulse width is 2.0ms (2.5ms. at +90° minus 0.5ms. at -90°). This is one tenth of the 20ms. pulse repetition rate (1/50 x 1000). Therefore, the range of programmable count values is one tenth of the maximum count. The rotation resolution is the range of motion of the servo, 180°, divided by the count range. This is summarized below<b>:</b></div>
<b>
<table style ="margin-bottom: 0.1in;">
<tr>
<td width = "10%" style="text-align: center;">Prescaler</td>
<td width = "10%" style="text-align: center;">Max Count</td>
<td width = "20%" style="text-align: center;">Pulse Width Count Range</td>
<td width = "20%" style="text-align: center;">Rotation Resolution</td>
</tr>
<tr>
<td width = "10%" style="text-align: center;">1</td>
<td width = "10%" style="text-align: center;">120,000</td>
<td width = "20%" style="text-align: center;">N/A</td>
<td width = "20%" style="text-align: center;">N/A</td>
</tr>
<tr>
<td width = "10%" style="text-align: center;">8</td>
<td width = "10%" style="text-align: center;">15,000</td>
<td width = "20%" style="text-align: center;">1500</td>
<td width = "20%" style="text-align: center;">0.12°</td>
</tr>
<tr>
<td width = "10%" style="text-align: center;">64</td>
<td width = "10%" style="text-align: center;">1875</td>
<td width = "20%" style="text-align: center;">187.5</td>
<td width = "20%" style="text-align: center;">0.96°</td>
</tr>
<tr>
<td width = "10%" style="text-align: center;">256</td>
<td width = "10%" style="text-align: center;">468.8</td>
<td width = "20%" style="text-align: center;">46.8</td>
<td width = "20%" style="text-align: center;">3.84°</td>
</tr>
<tr>
<td width = "10%" style="text-align: center;">1024</td>
<td width = "10%" style="text-align: center;">117.2</td>
<td width = "20%" style="text-align: center;">11.7</td>
<td width = "20%" style="text-align: center;">15°</td>
</tr>
</table>
</b>
<div style="margin-bottom: 0.1in;">From the chart above we can eliminate the prescaler value of 1 because the ATmega328 does not provide a timer/counter that can count to 120,000 (65535 or 255). The only way to employ an eight bit timer/counter (timer/counter 0, or 2) is to use the prescaler value of 1024 - the only choice where the maximum count is under 255. However, the resolution of 15° is poor. This means that we will use timer/counter 1 because it can count to 65535. We should go for the best resolution which means that we will use the divide by 8 prescaler. This gives a resolution of 0.12° per count </div>
<div style="margin-bottom: 0.1in;">Next we select the mode. We will select mode 8, the "Phase and Frequency Correct PWM" mode. The value of the maximum count will be programmed into register 1CR1. </div>
<div style="margin-bottom: 0.1in;">The script I wrote is below and the details of register programming is included within the comments. The script requires you to open a terminal window on the host computer - the Raspberry Pi in my case. You are asked to input a floating point number which is the desired degrees of rotation from the middle position. The script accepts values from -90° to +90°. Once it rotates the servo shaft to the angle you requested, it will ask for your input, again. </div>
<div style="margin-bottom: 0.1in;">Inputting a number from the terminal is not a trivial endeavor. The terminal handles one character at a time and it is up to the programmer to make sense of those characters. I did not want the script to be encumbered with the handling of the character inputs so I wrote a library to do that task. I wanted to learn how to do that, anyway, having not done that before. There are only three lines dealing with the character input<b>:</b> line 35 where we include the library dot h file, line 37 where we create an instance of the class created in the library, and line 59 where we call the function to get our number. My next post will report on creating that library function. </div>
<div style="margin-bottom: 0.1in;">The servo has three pins, two go the battery to power the device, and provide a ground reference, and the third is the control pin which receives the output from the ATmega328. Don't forget to connect the ground pin from the battery to one of the grounds of the Gertboard. </div>
<div style="margin-bottom: 0.1in;">The script<b>:</b></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<script src="https://gist.github.com/RaspPiGuy/9347019.js"></script>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-76156330111083952452014-03-03T19:07:00.000-05:002014-03-04T08:58:51.461-05:00Gertboard - Pulse Width Modulation - DC Motor Control<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;">This post is about using the ATmega328P microcontroller for Pulse Width Modulation. While the subject is covered pretty well in the device's data sheet, some clarification and simplification is in order. This is my intention here. Please have the datasheet available. <a href="http://www.atmel.com/devices/atmega328p.aspx">It can be found here. </a> Select the first pdf file.</div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">What is Pulse Width Modulation</h3>
<div style="margin-bottom: 0.1in;">If you landed on this page you probably know, so this explanation will be really short. While you can control a DC motor by controlling the voltage it is connected to, it is usually more precise and actually easier to control the motor by repeatedly turning it off and on. The motor responds to the average time the voltage is applied. You apply the motor voltage as a string of pulses with a defined frequency and a defined pulse width. If the duration of the pulse is half of the duration between pulses, the PWM will be 50% and the motor should turn at 1/2 speed. </div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">To Drive A DC Motor</h3>
<div style="margin-bottom: 0.1in;">My last blog entry used Timer/Counter 1 in Normal mode to produce a timed delay. The timed delay function only had to use the timer/counter to do one thing<b>:</b> count up to a value and issue an interrupt. Pulse width modulation has two requirements. It must establish a frequency of pulse repetition and control the width of the pulses. While interrupts can be generated, PWM typically controls the logic level of a pin, or pins, that connect to external devices. Let's start with the dc motor being that external device.</div>
<div style="margin-bottom: 0.1in;">We have plenty of options to consider. The first is whether we can use an eight bit timer/counter or do we need a 16 bit timer/counter. The answer is we probably don't need all of that resolution to control a dc motor. We can use ATmega's timer/counter 0 or 2 - both 8 bit circuits. Let's use timer/counter 0. </div>
<div style="margin-bottom: 0.1in;">Next we need to decide between two major PWM modes. One mode gives twice the maximum frequency of pulse repetition as the other. This "Fast PWM Mode" operates by having the counter count up, and when it reaches its upper value, the counter starts over at zero. If you were to graph count against time, you would see a sawtooth wave. The other mode, "Phase Correct PWM Mode" has the counter count up, and when it reaches its upper value, count down at the same rate. When the count reaches 0 it counts up again. Graphing this looks like a triangular wave. See my graphic below.</div>
<div style="margin-bottom: 0.1in;">Why are there two modes? If you never change the motor speed, either mode is fine. If you do change the motor speed, the Phase Correct PWM mode always has the center of the pulse at exactly the same place in time (if you keep the pulse repetition frequency the same and only change the pulse width). When changing the speed in Fast PWM the center of the pulse will move. Phase correct PWM results in a smooth transition in speed, while Fast PWM is more abrupt. Motors like the former over the latter. My example will use the Phase Correct PWM </div>
<div style="margin-bottom: 0.1in;">With that settled, we have to deal with the frequency of pulse repetition. I don't know enough about DC motors to say what is the best frequency of pulse generation. I guess if the frequency is too low, the motor could lose speed between pulses. I don't know if there is a down side of too high a frequency. The higher frequency could limit the resolution of the speed differences we can program. This will be clear soon. The frequency of pulse repetition rate is determined as follows: </div>
<div style="margin-bottom: 0.1in;"><b>Pulse repetition frequency = clock speed divided by the prescaler and divided again by the maximum count set into the timer counter and finally divided by 2</b></div>
<div style="margin-bottom: 0.1in;">My clock speed is 12MHz and the possible prescaler values are 1, 8, 64, 256, 1024 (allowable values for timer/counter 0). The lower the prescaler value the higher the frequency. The lower the count also gives you higher frequency. A little drawing is in order here:</div>
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC2sBoOm_GeJwbaX40I1wBfxy-zfAzwcASi32SEMBEZj4kLMkW9AnBekjMqDZ3MXEnnv-F4x_FKofVANqAzl1D7DDesDGhmg9a62xS9aGqYvZ0uTZislONch1LYms-s7KwphIQsYe0nSx2/s1480/PulseWodthModulation.jpg" imageanchor="1" style="margin-left: 0em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC2sBoOm_GeJwbaX40I1wBfxy-zfAzwcASi32SEMBEZj4kLMkW9AnBekjMqDZ3MXEnnv-F4x_FKofVANqAzl1D7DDesDGhmg9a62xS9aGqYvZ0uTZislONch1LYms-s7KwphIQsYe0nSx2/s592/PulseWodthModulation.jpg" /></a></div>
<div style="margin-bottom: 0.1in;">The slope of the triangular waveform is determined by the clock frequency and the prescaler value. The clock frequency is your system clock so is not a variable. The prescaler value is, however, programmable. The horizontal line at the top, "Frequency" is controllable by your program and represents the maximum count in the timer/counter. It should be clear that changing the maximum count changes the pulse repetition. If you lower the count, the peaks of the triangles move to the left decreasing the time between pulses. Generally, when you decide on a pulse repetition rate, you would keep that constant. </div>
<div style="margin-bottom: 0.1in;">The lower horizontal line, "Pulse Width", represents the width of the pulses. Typically, this value changes during your application. For example, if your project is a car with dc motors controlling two wheels, you frequently alter the speed of the car. And, you could steer the car by differentially changing the speed of each motor. Therefore, the width of the pulses frequently change. The graphic above should make it clear how the width of the pulses are changed. Lower the horizontal line and the width of each pulse decreases (assuming the we are talking about the positive going rectangle). </div>
<div style="margin-bottom: 0.1in;">Note that the count for the "Pulse Width" must be less than the "Frequency" count. The "Frequency" count then determines the resolution of the pulse width modulation. If the "Frequency" count is the maximum allowed, which is 255 for timer/counter 0, each count will correspond to a pulse modulation increment of about 0.4%. If you lowered that "Frequency" count to 10, you would only be able to program PWM in 10% increments.</div>
<div style="margin-bottom: 0.1in;">There is another programmable selection. The "Resulting Pulses" in the graphic are the result of selecting<b>:</b> clear (go low) on a compare match when counting up, and set (go high) on a compare match when counting down. The compare match value is represented in the above graphic by the line "Pulse Width". You can also program the opposite action<b>:</b> set on a compare match when counting up, and clear on a compare match when counting down. If you program that option, the "Resulting Pulses" waveform would be turned upside down. </div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Putting It Together In a Script</h3>
<div style="margin-bottom: 0.1in;">I did a small sample project where I control a <a href="http://www.adafruit.com/products/711">toy DC motor</a>. Since my ATmega328P resides on my Gertboard, I connect the motor and a 6V battery (4 AA's) to the BD6222HFP H-Bridge motor controller. This isolates the motor and it's power source from the PI and the Gertboard. My project increases the motor speed from off to full on, decreases the speed to off, changes the direction of the motor, increases the speed to the max and reduces it to off again. This action is repeated continuously. </div>
<div style="margin-bottom: 0.1in;">There are only two timer/counter 0 modes for Phase Correct PWM, mode 1 and mode 5. My project uses mode 5. Compare register OCR0A controls the "Frequency". If I use mode 1, the "Frequency" count would be fixed to 255. Using mode 5, I can select any value from 0 to 255. As it so happens, I chose 255 anyway. If I had two motors to control, I would choose mode 1. In that case, compare register OCR0A controls one motor and OCR0B controls the other. Pulse repetition frequency would be the same for both motors but each would have it's own PWM percentage. They could turn in the same or opposite direction from each other. </div>
<div style="margin-bottom: 0.1in;">The pulse repetition frequency of this project is 12,000,000 / (2 * 64 * 255) = 368 repetitions per second.</div>
<div style="margin-bottom: 0.1in;">The H-Bridge takes two inputs. One input gets the pulses from pin PD5 while the other input comes from pin PD7. PD7 will determine the direction of rotation just like reversing the leads to the motor. When PD7 is low, we will select clear on a compare match when counting up, and set on a compare match when counting down. When PD7 is high we select set on a compare match when counting up, and clear on a compare match when counting down. You can picture how this works by considering how you would stop the motor. The motor stops if both PD5 (PWM = 0%) and PD7 are the same polarity. </div>
<div style="margin-bottom: 0.2in;">The script below has a lot of comments (more comments than code) so I think the details are well presented within the script.</div>
<script src="https://gist.github.com/RaspPiGuy/9044911.js"></script>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-12185276641073718662014-02-12T13:40:00.000-05:002014-02-18T09:44:11.610-05:00Gertboard - Creating Delay Function With Timer/Counter<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<h3 style="font-size: 18px; margin-bottom: 0.15in;"></h3>
<div style="margin-bottom: 0.1in;">My last blog post mentioned that the Arduino built-in delayMicroseconds() function was very inaccurate. The error was a whopping 50% when measured with an oscilloscope. As I wanted to investigate some of the intricacies of the ATmega328P registers I thought to write my own delay function. </div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Counter - Timer Features of the ATmega328P</h3>
<div style="margin-bottom: 0.1in;">There is tons of information on the web about using the ATmega timer/counters so the following will be a bit sketchy. The datasheet is a must to have available when talking about the ATmega functions. However, the datasheet is rather terse so sometimes you have to read between the lines, experiment like I am doing, or read of someone else's experience like you are doing here. </div>
<div style="margin-bottom: 0.1in;">There are three timer/counters on the chip: 0, 1, and 2, They all have somewhat different features. Timer/counter 0, and 2, are eight bit counters so can only count up to a maximum of 255 (2<sup>8</sup>). Timer/counter 1, has a 16 bit counter so can count up to 65535 (2<sup>16</sup>). </div>
<div style="margin-bottom: 0.1in;">Timer/counters 0 and 2 are almost identical. It seems that the intended use for timer/counter 2 is as a real-time clock. It kind of assumes that a 32 kHz watch crystal is connected to pin TOSC1. However, on the Gertboard, and most Arduinos (as far as I know) The 12 or 16 MHz resonator is already connected to that pin. Timer/counter 2 does have six prescaler (clock divider) selections while 0. and 1 have five.</div>
<div style="margin-bottom: 0.1in;">Timer/counter 0 and 2, with their eight bit counters are well suited for controlling motors by pulse width modulation (PWM) while timer/counter 1 is best for servos and things my delay project. Timer/counter 0 and 2 have four modes of operation, a "Normal" mode, a "Clear Timer On Compare Match Mode" (CTC), and two pulse width modulator modes. Timer/counter 1 has all the modes of the other two with an additional PWM mode. </div>
<div style="margin-bottom: 0.1in;">In all but two of the modes, the counters in the timer/counter circuit count up with each clock pulse received. When it reaches either its maximum value (255 or 65535), or a value you program, it starts over from zero. For pulse width modulation, you use the counter to establish a period of time. But, that only gives you half of what is necessary to control motor speed. For each time period, you need to control the percentage of time that you provide voltage to your motor. To provide that functionality, each timer/counter has two comparators (8 bit for 0 and 2, and 16 bits for timer/counter 1). You program a value into a comparator and when the count in the counter matches that value, the state of the I/O pin associated with the Timer/counter/comparator changes. When the counter reaches it's top value and returns to zero, the state of the I/O pin changes again. This results in two changes of state in each counter cycle (OFF to ON, and ON to OFF or ON to OFF, and OFF to ON). There are two modes where the counter counts down as well as up. Here, the state of the I/O pin changes when the counter count matches the comparator while counting up to its maximum value and matches it again on its way down to zero. </div>
<div style="margin-bottom: 0.1in;">Since there are two comparators, each timer/counter can control two I/O pins. You can control two motors or two servos from each timer/counter circuit. The period (cycle time) would be the same for each because there is only one counter. However, each I/O can have its own percentage of ON/OFF time (because each has its own comparator).</div>
<div style="margin-bottom: 0.1in;">Beyond controlling I/O pins, the Timer/counters can be programmed to issue internal interrupts. That is the feature I use for my delay script. Each of the three timer/counters has three interrupts. For the modes where the counter only counts up, and then resets to zero, an interrupt is issued when the counter overflows - when it reaches its maximum value (255 or 65535). At the next clock pulse the counter resets to zero and the overflow flag interrupt is issued. For the two modes where the counter counts up and then down, the overflow interrupt is issued when the counter reaches the bottom (zero). The interrupt routine you write will clear that flag.</div>
<div style="margin-bottom: 0.1in;">The timer/counter can also be programmed to issue an internal interrupt when the counter count matches the comparator value. Since there are two comparators for each timer/counter, each has two of these interrupts.</div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">My Counter Project</h3>
<div style="margin-bottom: 0.1in;">My code:</div>
<script src="https://gist.github.com/RaspPiGuy/8710766.js"></script>
<div style="margin-bottom: 0.1in;">I use the timer/counter 1 in Normal mode and do not connect to either I/O pin. I don't use the comparator. I use the overflow flag interrupt. When my function is called, I do the following:</div>
<ol>
<li>The circuit only works for delays up to just over 5 seconds. If more is asked for, the maximum is substituted for the passed value.
<li>The most advantageous prescaler is selected depending upon the passed value. The lowest value possible is used to give the maximum resolution.
<li>The value of the count to be programmed into the time/counter 1 counter is calculated.
<li>A value of 1 is passed into the GPIOR0 register.
<li>Interrupts are turned off
<li>The two control registers associated timer/counter 1 are cleared assuring that the clock will not be connected to the counter (Counter will not count).
<li>The counter is programmed with the value calculated in step 3.
<li>Timer/counter Overflow Flag Interrupt is enabled.
<li>The prescaler is selected according to the variable "msk". This starts the clock. The clock now starts to count up with from the value we programmed into it (step 7.).
<li>Interrupts are enabled.
<li>We go into an endless loop waiting for the interrupt.
<li>The interrupt is issued one clock pulse after the counter reaches its maximum value of 65535.
<li>Processing enters the interrupt service routine which clears the interrupt.
<li>The value of GPIOR0 is set to zero.
<li>The prescaler is set to None value which stops the clock
<li>The Overflow Flag Interrupt is disabled.
<li>We exit the interrupt service routine and go back into the endless loop.
<li>Since GPIOR0 is now not 1, we exit the endless loop and the function.
</ol>
<div style="margin-bottom: 0.1in;">The prescaler divides the 12MHz clock. For example, if the prescaler is set to 8, it takes eight clock cycles of the 12MHz clock to send one clock pulse to the counter. The available prescale values are None, 1, 8, 64, 256, and 1024. NONE disconnects the clock from the counter. If the prescaler is set to 1, it takes 65536 / 12MHz or 5461.3 microseconds to count from 0 to 65536 (65536 is equivalent to 0). The maximum delay for the function is obtained when the prescaler is 1024 and the variable "count" is 0, which would be 65536 x 1024 / 12MHz which is 5592405.3 microseconds or 5.5924053 seconds. Any value passed to the function greater than 5592405.3 is set to 5592405.3. I guess I could have extended the time indefinitely by waiting for multiple occurrences of the interrupt before exiting the endless loop. I saw no need to do that because the built-in delay() function is pretty accurate.
</div>
<div style="margin-bottom: 0.1in;">In step 3. above, I make use of the GPIOR0 register, one of three general purpose I/O registers. These registers can be used to store any information. I use it here instead of using another variable. If I had used a variable, instead, that variable would had to be declared as volatile. If I had written line 75 as "while (somevariable == 1);", and had not declared "somevariable" as volatile, the compiler would have thought the line did nothing except create an endless loop and would have eliminated it. The use of the register is kind of handy.</div>
<div style="margin-bottom: 0.1in;">There are control bits that need to be programmed: Four WGM1 (waveform generator mode) bits, and two sets of two COM1 (Compare Output Mode) bits. One set of COM1 bits correspond to each comparator circuit. In this application, WGM1 is programmed to 0b0000, which selects Normal mode. Both COM1 sets are programmed to 0b00, which disconnects the two I/O pins associated with timer/counter 1 from the two timer/counter 1 waveform generator circuits. The four COM1 bits, and the lower two bits of WGM1 are part of the TCCR1A register (other two bits are not used). Therefore, TCCR1A is programmed to 0. The two higher order WGM1 bits are bits 3 and 4 of the TCCR1B register. Bits 0, 1, and 2 of TCCR1B are devoted to the prescaler. The value in the variable "msk" is used to program these bits. The range of possible values of "msk" is only be 0b00000001 through 0b00000101 (1 through 5), which keeps the bits 3 through 7 as a "0". </div>
<div style="margin-bottom: 0.1in;">The overflow interrupt is selected to be enabled when interrupts are enabled. The prescaler is loaded with the value in "msk" which starts the counter counting up from the value in "count". Interrupts are enabled and we enter the endless loop. When the counter overflows (next clock after reaching 65535) the interrupt occurs and we leave the endless loop and enter the interrupt service routine. The interrupt service routine changes the value of GPIOR0 and stops the counter from counting. We leave the interrupt service routine and return to the endless loop. Since GPIOR0 is no longer 1, we leave the loop and leave the del() function. </div>
<div style="margin-bottom: 0.1in;">In the next blog post I will discuss PWM. using the timer/counter features of the ATmega328P.</div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-70425073427062725452014-01-19T17:10:00.000-05:002014-01-19T17:10:11.558-05:00Gertboard - Programming With ATmega Registers<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Arduino IDE Built-in Functions Vrs. Direct Register Programming</h3>
<div style="margin-bottom: 0.1in;"><b>Functionally, what is the difference between this script:</b></div>
<script src="https://gist.github.com/RaspPiGuy/8483041.js"></script>
<div style="margin-bottom: 0.1in;"><b>and this script:</b></div>
<script src="https://gist.github.com/RaspPiGuy/8378741.js"></script>
<div style="margin-bottom: 0.1in;"><b>Answer: NOTHING</b></div>
<div style="margin-bottom: 0.1in;"><b>Note:</b> In the sketches discussed here, to see if the LEDs on the Gertboard are ON or OFF, PB0 is connected to BUF1, PB1 to BUF2, PB2 to BUF3, PB3 to BUF4, PB4 to BUF5, and PB5 to BUF6.</div>
<div style="margin-bottom: 0.1in;">Both scripts turn LEDs on the Gertboard ON and OFF. First, LEDs 1, 3, and 5 are ON with 2, 4, and 6 OFF. One second later, 1, 3, and 5 are OFF, and 2, 4, and 6 are ON. One second later, the process repeats itself, on and on. The first script uses functions built into the Arduino IDE. While the second script uses the Arduino IDE delay() function, the LEDs are controlled by writing directly to microcontroller registers. The second script is sure a lot shorter and takes up about half of the space in memory. I must admit that it does use a little trick that I'll discuss later. That trick can not be used with the first script. I tried to shorten the first script by using <b>for</b> loops and <b>if/else</b> statements in lines 12 - 27. I gave up because it didn't seem to save lines of code.</div>
<div style="margin-bottom: 0.1in;">The built-in functions that are part of the Arduino IDE are a convenient way to interface with the ATmega I/O pins. The second script shows another method, and that is to communicate directly with registers within the microcontroller associated with those I/O pins. Registers are eight bit bytes that are addressable within the ATmega memory space. In most cases, each bit of a register can be either read or written to. Each bit, or a combination of bits control some function or produce some effect. Before you can deal with these registers you need knowledge of what the registers do. That knowledge comes from the <a href="http://www.atmel.com/devices/atmega328p.aspx">ATmega datasheet from Atmel</a>. </div>
<div style="margin-bottom: 0.1in;">If you are not concerned about writing a few more lines of code or how many bytes get loaded into the microcontroller, what other reasons would there be for programming ATmegta registers? Here are a few reasons:</div>
<ul>
<li>IT'S EASY TO DO. There is a library include file, iom328p.h for the ATmega328P, that defines all of the registers and register pins in exactly the same way that they are named in the datasheet. For example, in the second sketch, the line "DDRB=0b00111111;" correlates directly to 13.4.3 on page 92 of the datasheet. This is the datadirection register for port B. Writing a 1 to the lower six bit positions makes pins PB0 to PB5 outputs. "PORTB=0b00101010;" correlates to 13.4.2 on page 92. This will make PB1, PB3, and PB5 logic high, turning on their respective LEDs. The first line of that second script, "#include <avr/io.h>" looks to see what ATmega chip you are using and, in our case, the ATmega328P. When the script is compiled, the definitions in iom328p.h are used to figure out the locations within the ATmega to access.
<li>There are things you can do that are not supported by the built-in functions. For example, even though you can do PWM to control a motor using analogWrite(), you are stuck with one frequency - about 490Hz. If your motor would rather work at 10khz, you can program the counter registers. There are a lot more things you can do or develop yourself. For instance, I wish to develop my own 1-Wire interface for use with my DS18B20 temperature sensors.
<li>I found that the function delayMicroseconds() produces delays that area about 2/3 of the correct values. I noticed this first with my camera remote control project. I was looking for a pulse width of 284usec but had to program delayMicroseconds(415) to get 284usec. Testing with an oscilloscope, from a desired delay of 10 to 3000usec, I consistently measured about 67% of the desired value (the delay() function is pretty accurate). So, I plan to write my own function for microsecond delays. There are two 8 bit counter/timers and a 16 bit counter/timer accessible by registers that can be utilized.
<li>For me, I like getting closer to the hardware when programming. It makes me feel more in control.
<li>Gives me a chance to use those fun bitwise operators like OR, AND, and EXCLUSIVE OR and shift bigs right and shift bits left.
<li>Here are most of the ATmega functions that are accessible through registers:
<ul>
<li>I/O Pins, both content, data direction, and pull-up resistors for inputs
<li>The various counter timer registers and prescallers for 8 and 16 bit counter/timers. These also control the PWM oscillator functions at the I/O pins
<li>SPI control, status, and data registers
<li>Registers for the serial communications using the USARTs
<li>Registers for the 2-Wire serial interface
<li>Analog comparator
<li>A to D converter
<li>Interrupts
</ul>
</ul>
<div style="margin-bottom: 0.1in;">I said I like to use bitwise operators, and the EXCLUSIVE OR operator is the trick I used to make that second script so short. Line 7 turned three of the six LEDs on (PB1, PB3, and PB5). Line 12 is going to toggle those LEDs that are ON to OFF and those that are OFF to ON. </div>
<div style="margin-bottom: 0.1in;">Line 12 uses a compound operator. Recall that =+ is a compound operator. The expression A =+ 1 is the equivalent to A = A + 1. In our line 12, the compound operator is =^ which is an EXCLUSIVE OR. It is the equivalent of PORTB = PORTB ^ 0b001111. The EXCLUSIVE OR compares two bits. If they are the same (both 0 or both 1) the result is a 0. If they are different, the result is a 1. Let's apply that to PORTB which we will assume is 00101010. Putting one number under the other let's see what we get:</div>
<div> 00101010 PORTB</div>
<div> <u>00111111</u> EXCLUSIVE OR with this binary number</div>
<div style="margin-bottom: 0.1in;"> 00010101 NEW PORTB value</div>
<div style="margin-bottom: 0.1in;">Let's do that again:</div>
<div> 00010101 PORTB</div>
<div> <u>00111111</u> EXCLUSIVE OR with this binary number</div>
<div style="margin-bottom: 0.1in;"> 00101010 NEW PORTB value</div>
<div style="margin-bottom: 0.1in;">Note we are back to where we started. I hope you can see that this operation will toggle the six LEDs ON and OFF.</div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Another Sketch Writing To I/O Pins</h3>
<div style="margin-bottom: 0.1in;">I would like to introduce another sketch. This one uses four bitwise operators. Between the two sketches we will have used all of the bitwise operators except for the shift right.</div>
<script src="https://gist.github.com/RaspPiGuy/8378773.js"></script>
<div style="margin-bottom: 0.1in;">This sketch uses the same six LEDs on the Gertboard except only one LED is lit at any one time. It starts with all LEDs OFF, then lights each LED for one second starting with the LED connected to pin PB0. Each LED, down the line, is ON for one second. One second after PB5 is lit, the sequence starts over again at PB0. </div>
<div style="margin-bottom: 0.1in;">Let's take a look at line 12. Here we have two bitwise operators, an OR compound operator, |=, and a SHIFT LEFT, operator, <<. If you are not familiar with this type of notation it surely looks strange. </div>
<div style="margin-bottom: 0.1in;">Line 12 means we are going to take the current contents of the register PORTB, the register connected to pins PB0 through PB5, and OR them with some value so that PORTB is changed. I'll talk about what OR means in a minute. For now, the question is: what is that value we are going to use to change the contents of PORTB? Why, it is (1 << PORTB0), of course. What?? What does that mean? If you look into the include file, iom328p.h, (called by avr/io.h, the first line in the sketch) you will find that PORTB0 is defined as 0. In like manner, PORTB5 is defined as 5. You can see the pattern here. So, (1 << PORTB0) becomes (1 << 0). That means we take the number 1 and shift it left 0 times. That seems to make even less sense. It begins to make sense, however, if we look at 1 as 00000001. Nothing much happens to it if we shift it 0 times as in line 12 of the sketch. But, what about similar line 32. This means we shift 1 left by 5. Just move that 1 over 5 places to the left. This new value now becomes 00100000. Get it?</div>
<div style="margin-bottom: 0.1in;">Now, we can talk about the OR operator. When we OR two binary digits, if either digit is a 1, the resulting value is a 1. A 0 result only corresponds to both digits being 0. So, if we started out with PORTB as 0b00000000 (all LEDs OFF) let's apply sketch line 12 and see what happens.</div>
<div> 00000000 PORTB</div>
<div> <u>00000001</u> OR with this binary number</div>
<div style="margin-bottom: 0.1in;"> 00000001 NEW PORTB value</div>
<div style="margin-bottom: 0.1in;">This obviously turns the LED connected to PB0 ON, and that is the only one on. Now we wait one second and move on to sketch line 15, which is similar to line 12, except that the |= is replaced by &=, the AND compound operator. And, (1 << PORTB0) is now: !(1 << PORTB0). The exclamation point is the NOT symbol, for negation, another bitwise operator. We know that (1 << PORTB0) is 00000001. What then is !(00000001)? The answer is 11111110. Every bit is changed to its complement (1 becomes 0, 0 becomes 1). </div>
<div style="margin-bottom: 0.1in;">The AND bitwise operator takes two bits and if either is a 0, or both are 0, the result will be a 0. The only way to get a 1 is if both bits are 1. So let's AND the contents of PORTB, 00000001, with 11111110:</div>
<div> 00000001 PORTB</div>
<div> <u>11111110</u> AND with this binary number</div>
<div style="margin-bottom: 0.1in;"> 00000000 NEW PORTB value</div>
<div style="margin-bottom: 0.1in;">This turns the PB0 LED OFF. Obviously we could have written PORTB = 0; with the same effect, but what is the learning value in that? If you follow the logic you can see where sketch line 16, and beyond, turns the LED connected to PB1 one, for a second, before turning it off, and turning the next LED on, etc., etc.</div>
<div style="margin-bottom: 0.1in;">Controlling those LEDs the way I did in that last sketch is rather silly. Lines 12 through 35 could have been written as:</div>
<div>PORTB = 0b00000001;</div>
<div>DELAY(1000);</DIV>
<div>PORTB = 0b00000010;</div>
<div>DELAY(1000);</DIV>
<div> <b>.</b></div>
<div> <b>.</b></div>
<div> <b>.</b></div>
<div>PORTB = 0b00100000;</div>
<div style="margin-bottom: 0.1in;">DELAY(1000);</DIV>
<div style="margin-bottom: 0.1in;">So why did I write all of that extra code? I wanted to illustrate the use of those bitwise functions because they are invaluable when writing to registers and memory. They are an elegant way of accessing individual bits in a field of other bits (our field is 8 bits because all ATmega registers are eight bits long). It's a way of altering some bits while leaving other bits alone. You could keep track of all the bits in a register at all times, but sometimes that is not possible. Other processes, either hardware or software, could change some bits in a register. You only want to access the bits you want to change and leave the others alone. </div>
<div style="margin-bottom: 0.1in;">As you can see from what we have done before, if you wish to make a bit a 1, or assure it is a 1, OR it with a 1. OR the bits you don't want to change with a 0. Look at the example above.</div>
<div style="margin-bottom: 0.1in;">If you wish to make a bit a 0, or assure it is a 0, AND it with a 0 and AND the others with a 1 to leave them alone. If you wish to toggle a bit, changing it from a 0 to a 1, or a 1 to a 0, EXCLUSIVE OR it with a 1, and EXCLUSIVE OR the others with a 0. If you study the examples above you can see how that works.</div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Sketch To Read From I/O Pins</h3>
<div style="margin-bottom: 0.1in;">I talked about writing to I/O pins in the previous sketches, so my last sketch shows an example of reading the logic level of an I/O pin:</div>
<script src="https://gist.github.com/RaspPiGuy/8378807.js"></script>
<div style="margin-bottom: 0.1in;">This sketch sets pins PC0 to PC5 as inputs. Writing to PORTC will determine if an internal pull-up resistor will be connected to the pin. Writing a 1, connects the pull-ups. So writing 3F, in hexidecimal, writes a 1 to the lower 6 bits of the register. </div>
<div style="margin-bottom: 0.1in;">Every second, the script sends the contents of PINC to the serial monitor running on the Pi. If PORTC is the register that outputs a logic level to the port C I/O pins, PINC is the register that records the logic level of external inputs of the port C I/O pins. If nothing is connected to an external pin, the internal pull-up resistor will set a logic 1 in the corresponding PINC register bit. If you connect that pin to ground, a logic 0 will be set in the register bit. Using the BIN built-in constant, will send the contents of the register in binary format.</div>
<div style="margin-bottom: 0.1in;">If there is nothing connected to any of the port C pins, you will see:</div>
<div> 111111</div>
<div> 111111</div>
<div> 111111</div>
<div style="margin-bottom: 0.1in;">etc.</div>
<div style="margin-bottom: 0.1in;">However, if you connect PC0 to ground, for example, you will see:</div>
<div> 111110</div>
<div> 111110</div>
<div style="margin-bottom: 0.1in;">etc. for as long as the ground is connected.</div>
<h3 style="font-size: 18px; margin-bottom: 0.15in;">Wrapup</h3>
<div style="margin-bottom: 0.1in;">I hope this has been informative and if you are a beginner that you learned somethings useful.</div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-20989952516699165392014-01-11T16:35:00.000-05:002014-01-11T16:37:06.625-05:00Gertboard - Changing ATmega328P Resonator Frequency <span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;">In my last post about my Camera Remote Controller project, I said I would discuss changing the ATmega resonator frequency. </div>
<h3>Why Change The Frequency</h3>
<div style="margin-bottom: 0.1in;">Now why would you want to do that? Here is a good reason why: once you program the ATmega microprocessor via the RaspberryPi/Gertboard programmer you can remove the chip from the Gertboard and install it on your own PCB. That is what I did to make my Camera Remote Control project become useful rather than being a collection of loose parts and connections. Freed from the Gertboard you are no longer restricted to using a 12MHz external frequency source. You could power your project from 5V rather than the Gertboard's 3.3V allowing you to use a 16MHz resonator or a 16MHz crystal. Perhaps you found a script that was written for an Arduino that you would like to use. Most Arduinos run on 16MHz not 12MHz.</div>
<div style="margin-bottom: 0.1in;">I got interested in this question because I stupidly ordered a bunch of 10MHz resonators. I did this because I failed to check the schematics and THOUGHT the resonator was 10MHz, not 12MHz. I discovered my error but figured the camera remote would work OK at 10MHz, so I wondered how the frequency is set. </div>
<h3>Importance Of Clock Frequency</h3>
<div style="margin-bottom: 0.1in;">I guess I should talk about why the clock frequency is important. It's important if you are doing any timing. Timing is accomplished by using one of the Arduino IDE builtin functions such as delay(), delayMicroseconds(), micros(), and millis(), or by writing your own timing functions. It's also a consideration if you want to have a script work exactly the same on and off the Gertboard. If you have a project where the timing is not critical, and speed is not a factor, you could forget about an external clock source and use one of the ATmega internal clock options. More on this later.</div>
<h3>Let's Change The Frequency</h3>
<div style="margin-bottom: 0.1in;">OK, if I still have your interest, what do you do if you want to change the clock frequency? Where is the clock frequency set? It is not set by programming any of the fuses or by programming any of the ATmega registers. It is set when you compile your script from whatever makefile is in use. Let's be clear about one thing here, I am talking about writing scripts, compiling them, and uploading them using the Arduino IDE. If that is the case, the makefile seems to be hidden from view. At least, I could not find it. However, there is a way to find out what is going on when you compile a script. </div>
<div style="margin-bottom: 0.1in;">Bring up your Arduino IDE and go to "File/Preferences", then enable "Show verbose output during compilation". Compile any script. You will find it takes much, much longer and a lot of messages scroll by at the bottom of the window. You should see calls to avr-g++ and avr-gcc, each with several of parameters. One of those parameters will be "-DF_CPU=12000000". OK now that we see that, how do we change it? To answer that you have to know where the makefile knows that the parameter should be 12000000. It finds that information in the following file: </div>
<div style="margin-bottom: 0.1in;"> <b>/usr/share/arduino/hardware/arduino/boards.txt.</b></div>
<div style="margin-bottom: 0.1in;"><b>boards.txt</b> contains configuration information for products that can use the Arduino IDE like the Gertboard. You can find sections for the Arduino Uno, the Arduino Nano, the LilyPad and many of others. Heading the file are the two sections for the Gertboard which were probably added by Gordon Henderson. One section is for each of the two ATmega ICs you could use with the Gertboard: the ATmega328 and the ATmega168. Assuming you are using the ATmega328, the line in <b>boards.txt</b> we are looking for is this one: </div>
<div style="margin-bottom: 0.1in;"> <b>gert328.build.f_cpu=12000000L</b>. </div>
<div style="margin-bottom: 0.1in;">To change the frequency, simply change the 12000000 to some other value. <b>But, </b>if you compile a sketch, change the value of f_cpu, and immediately recompile your sketch, <b>you will not see a change (in verbose mode) to the parameters of avr-g++ and avr-gcc.</b> When you recompile the same sketch that you last compiled, the Arduino IDE attempts to speed things up a bit (so it doesn't try your patience), and, apparently, does not look at <b>boards.txt</b> again. So, after changing <b>board.txt</b>, compile a different sketch or kill and restart the IDE. Then, you will see the change to -DF_CPU. As usual, make a backup copy of <b>boards.txt</b> before making any changes. </div>
<div style="margin-bottom: 0.1in;">I tried this out by writing a sketch to toggle an LED on and off at a one minute rate. Changing the clock frequency as described above altered the cycle time in a predictable manner.</div>
<h3>Changing The Clock Source</h3>
<div style="margin-bottom: 0.1in;"><i>I have not personally tried changing the clock source as described in the following. But, I don't see why it would not work.</i></div>
<div style="margin-bottom: 0.1in;">If timing is not important and your project does not have to work at lightning speed when you remove your ATmega chip from your Gertboard, and install in in your own hardware, you do not really have to install a resonator or crystal.</div>
<div style="margin-bottom: 0.1in;">Before I continue, I strongly suggest you have a copy of the datasheet (it's hardly a sheet, it's 660 pages) for the microcontroller. <a href="http://www.atmel.com/devices/atmega328p.aspx">You can find it here from Atmel.</a> Make sure you download the first .pdf file under the picture. I'll assume you have this handy in the following discussions. </div>
<div style="margin-bottom: 0.1in;">From Table 9-1 on page 27 you can see that, besides the three external clock options, there are two internal clocks built into the chip: a "Calibrated Internal RC Oscillator", which runs at 8MHz, and an "Internal 128KHz RC Oscillator". The default selection is the 8MHz calibrated oscillator. There is also a prescaller that divides the oscillator by any one of the eight values shown on Table 9-17 on page 37. The default value is to divide by 8. This prescaller will also divide the frequency of any of the external clock choices you may have choosen.</div>
<div style="margin-bottom: 0.1in;">If the default choice is the 8MHz oscillator divided down to 1MHz, how does the Gertboard run at 12MHz? The answer is: The Gertboard does not use the default settings if you followed Gordon Henderson's direction for setting up the ATmega chip before using it. Whenever you use the Gertboard for the first time, <b>or install a new ATmega chip on the Gertboard,</b> you run a program called <b>avrsetup. avrsetup</b> programs several registers within the chip, namely the three fuse registers and a lock byte. We won't be talking about the lock byte because <b>avrsetup</b> just programs the lock byte to its default configuration.</div>
<div style="margin-bottom: 0.1in;">If you are younger than about 50, you might wonder why they are called fuse registers. Miorocontroller chips, as well as other chips, like old PROMS (programmable read only memory), would be programmed by burning out fuseable links within the chip. A popped fuse represented a logic 0 while an intact fuse was a logic 1. Once the chip was programmed and you wanted to revise the information, you threw out the old chip and programmed a new one. I don't think any modern devices have fuses - but the name has endured. Mainly, these registers contain settings you want to setup before you do any serious programming because making changes later could mess up what you already programmed. </div>
<div style="margin-bottom: 0.1in;"><b>avrsetup</b> programs these fuse registers for you by calling a program called <b>avrdude</b>. The three registers are the "Extended Fuse Byte", the "Fuse High Byte", and the "Fuse Low Byte". These are all eight bits in length. You can see what these registers do in section 28.2 starting on page 286. If you compare these registers with <b>avrsetup</b> you can see that the extended and high fuse registers are left at their defaults. </div>
<div style="margin-bottom: 0.1in;">The low fuse register is definitely changed. The default value is 0x62 specifying the 8Hz calibrated oscillator and prescaller set to divide by 8. See Table 28-9 on pages 288 and 289 and Table 9-1 on page 27. <b>avrsetup</b> changes that setting to 0xE7 which selects the "Full Swing Crystal Oscillator", for the 12MHz resonator on the Gertboard, and prescalling set to 1. </div>
<div style="margin-bottom: 0.1in;">Like <b>boards.txt, avrsetup</b> can be changed by the user. But, please, make the changes carefully and make a backup of <b>avrsetup</b>. If you would like to accept the 8MHz calibrated oscillator divided by 8, don't run <b>avrsetup</b> at all because all of the fuse registers and the lock byte will be set to the factory defaults.</div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-56354161691025812812014-01-06T11:00:00.000-05:002014-01-06T13:39:05.149-05:00Camera Remote Control - Free To Move<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;">Last August I published four posts about my camera remote control project. I have a remote receiver/transmitter for actuating the shutter of my Canon G1X. The project was to replace the transmitter so I could control the shutter with a motion detector. Luckily I was able to find out that the receiver works at 433MHz. </div>
<div style="margin-bottom: 0.1in;">The heart of the system consists of a 433MHz transmitter, a motion detector, and an ATmega328P microcontroller IC. Everything connected to my Gertboard, which sits atop my Raspberry Pi. The project was very successful but not terribly useful because it was basically a bunch of loose components and wires. And, it was tethered to a power cord. Here is what it looked like:</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisY0YK8FnzFu182gvOEVavoJ2eC4nSBGf9t7vUy7V0EOfn0A00SMsQQ3s5ThWvgT0OFjOxUw1QbFMhmRYQsIzQfv-dOJ8vVJVWt3-1MInZ5p0U5H0rUGYC5vqJsQJ9Emof8MGLRTo9BjuI/s1600/Pi-Gertboard-RemoteXmitter-MotionDetector+withText.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisY0YK8FnzFu182gvOEVavoJ2eC4nSBGf9t7vUy7V0EOfn0A00SMsQQ3s5ThWvgT0OFjOxUw1QbFMhmRYQsIzQfv-dOJ8vVJVWt3-1MInZ5p0U5H0rUGYC5vqJsQJ9Emof8MGLRTo9BjuI/s400/Pi-Gertboard-RemoteXmitter-MotionDetector+withText.jpg" /><div class = "caption"><i>Camera Remote Project</i></div></a></div></div>
<div style="margin-bottom: 0.2in;">To make it useful, everything had to be separated from the Gertboard, RaspberryPi, and AC power. That's possible because the microcontroller, once programmed, retains its program. It was then just a matter of carefully removing the microcontroller from the Gertboard, wiring everything up, and putting it in a box. Oh, and using battery power rather than AC. Here you can see the completed camera remote in its enclosure and a really short demonstration of it in action:</div>
<div style="margin-bottom: 0.2in;"><iframe width="560" height="315" src="//www.youtube.com/embed/Rg3ia5L1sNA?rel=0" frameborder="0" allowfullscreen></iframe></div>
<div style="margin-bottom: 0.1in;">And here is a photo of the inside of the box:</div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPBZzhHz9h4rMsWSO5Scelg5QqrhDCBl55-A8UBaInvlSEW8X_-VaKHGy6tVB_R4kb6iq6srfSuFl9457J8RbV_e4aQMWo_w0xoqKRQ6YkrYvNx2jsDsQX2Eq4D_ihGMwE8yFD6OJWbjYP/s1200/IMG_0693.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPBZzhHz9h4rMsWSO5Scelg5QqrhDCBl55-A8UBaInvlSEW8X_-VaKHGy6tVB_R4kb6iq6srfSuFl9457J8RbV_e4aQMWo_w0xoqKRQ6YkrYvNx2jsDsQX2Eq4D_ihGMwE8yFD6OJWbjYP/s300/IMG_0693.jpg" /><div class = "caption"><i>Inside the Enclosure</i></div></a></div></div>
<div style="margin-bottom: 0.1in;">The circuit is built up on Adafruit's <a href="http://www.adafruit.com/products/571">Perma-Proto Half-sized Breadboard PCB</a>. The schematic follows here. </div>
<div style="margin-bottom: 0.1in;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9CZoDDFRDIncqAd5jwyv9r6JgHTttpUF22ht2RSstFY6oNER5OYRoo_sUYj5QfpiL71uwvUej5_NxynxD9VXiht5dJLaMh1IcICi4i1xUU5WzbZNt9kUSGXlDXDtXyvQT7DzhLtlBc3PV/s1520/Resize+of+CameraRemoteSchematicsA_1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9CZoDDFRDIncqAd5jwyv9r6JgHTttpUF22ht2RSstFY6oNER5OYRoo_sUYj5QfpiL71uwvUej5_NxynxD9VXiht5dJLaMh1IcICi4i1xUU5WzbZNt9kUSGXlDXDtXyvQT7DzhLtlBc3PV/s608/Resize+of+CameraRemoteSchematicsA_1.jpg" /><div class = "caption"><i>Camera Remote Schematics</i></div></a></div></div>
<div style="margin-bottom: 0.1in;">The original project used two LEDs that were part of the Gertboard. Of course, these were not available in the stand alone version, so I added two LEDs to the circuit. As before, one LED tracks the output of the motion detector. When the motion detector is triggered, its data signal output goes high for about a second. This time is variable and is controlled by a potentiometer on the detector PCB. This hold time prevents a series of rapid triggers. On the video above, that is why you see that LED on for about a second. The other LED is only on for the time it takes to send patterns to the RF transmitter - a very short time. In the video you have to look closely to see this flash. The LEDs are mounted in the top of the enclosure. </div>
<div style="margin-bottom: 0.1in;"><a href="http://thepiandi.blogspot.com/2013/08/gertboard-project-camera-remote-control.html">You can follow this link </a>to see the diagram of the project as it was on the Gertboard, and to find links to the RF transmitter and the motion detector.</div>
<div style="margin-bottom: 0.1in;">When it comes to purchasing components for these projects we always seem to mention Adafruit, SparkFun, and Element14/Newark Electronics. However, I find the best place to go for general electronic parts and hardware is <a href="http://www.digikey.com">Digi-Key </a>. I could not find the enclosure, 12MHz resonator, and many of the nuts and bolts I needed elsewhere. </div>
<div style="margin-bottom: 0.1in;">The Gertboard uses a 12MHz resonator, which I found was not a common part. 10MHz and 16MHz can be easily found. I wondered what to do if I decided to use a resonator of another frequency rather than 12MHz. I will report on that effort on another blog post. I did use the 12MHz resonator and was glad I did. I'll also report on that in a separate post.</div>
<div style="margin-bottom: 0.1in;">The enclosure for the project is a Bud box. Digi-Key has a good assortment of these enclosures.</div>
<div style="margin-bottom: 0.1in;">You may notice rather large series resistors for the LEDs - 10Kohm each. This limited the current to the LEDs to about 1ma. This was just fine because I used clear LEDs so it doesn't take much light to be visible. This also limited the battery current draw. </div>
<div style="margin-bottom: 0.1in;">I used three AAA batteries in series to produce 4.5V for the project. The battery holder came from Adafruit and, unfortunately for me, had an on/off switch. The switch was in the way because it was on the side of the battery holder that I superglued to the side of the enclosure. It took a bit of work to remove enough of the switch to make it flush. The plastic was tough. Also, the width of the holder was about 1mm too wide. This interfered with the lid of the enclosure. I had to use a belt sander to take a little bit of plastic away. It wound up being a mess, and I need tape to hold the battery compartment lid on. The batteries should last a pretty long time. The circuit draws about 9ma. During the time the motion detector is triggered, the current rises to about 12ma.</div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0tag:blogger.com,1999:blog-7443803799514447902.post-64301131450344399702013-11-12T11:01:00.000-05:002013-11-12T14:22:37.308-05:00Adding Graphical Users Interface to Graphing Temperature Measurements<span style="font-family: Times, "Times New Roman", serif; font-size: 14px;">
<div style="margin-bottom: 0.1in;">I started a series of blog posts back in July about making temperature measurements with sensors using the one-wire interface to the Pi. I described the hardware, software requirements, and the python script I wrote to make and report the measurements. </div>
<div style="margin-bottom: 0.1in;">Earlier this month, I added graphing capability using RRDtool and PyRRD. The python script is, of course, included. Prior to that post, I presented a tutorial on programming with RRDtool and PyRRD. The graphical results are pretty impressive. My only complaint concerns actually running the script. Before making any measurements, the user has to answer quite a few questions that appear on the terminal. Answering all of those questions, each time I run the script, got a bit tedious, so I thought about adding a graphical users interface, i.e. popping a window for those questions and answers. This post reports on those efforts. </div>
<div style="margin-bottom: 0.1in;">Before proceeding any further, I hope you readers have taken a look at my post proceeding this one (Oct. 18). While developing and testing my GUI I ran into a serious problem. The script must be run from root because of access to the the GPIO hardware on the Pi. I found that Linux would not give me permission to access the graphical system running as root. Look at that post to see how that problem was handled.</div>
<div style="margin-bottom: 0.1in;">When you launch the script here is the <b>default</b> window that pops up. I'll talk about why I mentioned default window in a little bit:</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUMzJ412uSzN4l55H6-cHb-CJP2g7wjOtKriqWr3OG-r0_DHvTecFAnhOP16q-DjCwOBEb-x01_kiaQrAoy0P63Ql2eO2TSm3EZEOVpvFXrwIy-HPVh4L5Niyet2wIwSAl5fSDxMWQZk9m/s1440/GUI+For+Graph+Temperature+1.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUMzJ412uSzN4l55H6-cHb-CJP2g7wjOtKriqWr3OG-r0_DHvTecFAnhOP16q-DjCwOBEb-x01_kiaQrAoy0P63Ql2eO2TSm3EZEOVpvFXrwIy-HPVh4L5Niyet2wIwSAl5fSDxMWQZk9m/s576/GUI+For+Graph+Temperature+1.bmp" /><div class = "caption"><i>Default Window</i></div></a></div>
<div style="margin-bottom: 0.1in;">Taking this from the top of the window, I'll discuss each of the widgets, in turn: I have two temperature sensors, one on the breadboard the other on the end of a cable. With the radio buttons I can choose either sensor, or choose both sensors. You might think two check boxes would be more appropriate than the three radio buttons. But, the radio buttons work better with the program that actually makes the measurements (the program that calls for the GUI window).</div>
<div style="margin-bottom: 0.1in;">Next are two entry boxes for applying a legend to the graph for each sensor. The default has only the breadboard sensor enabled because of the radio buttons selection above, which is why the cable entry box is grayed out. Select cable sensor and the entry box for cable can be edited and the breadboard entry box is grayed out. Select both sensors and neither entry box is grayed out. If you don't type anything in the entry boxes the default text (as shown) will appear on the graph. RRDtool has its own rules and some may seem strange. Here, for example, if you wish to have a colon in your legend (cable: water temperature), you must escape the colon with the backslash character (cable\: water temperature). </div>
<div style="margin-bottom: 0.1in;">After the legend comes the title for the graph. A default string is included. RRDtool does not require you to escape colons in the title, but does require you to escape spaces.</div>
<div style="margin-bottom: 0.1in;">Comments are optional. You must escape colons here too, just like the legends.</div>
<div style="margin-bottom: 0.1in;">Next we can choose the graph background color. Black, I think, looks good on the screen, but if you wish to send the graph to your printer, it would use an awful lot of ink. Consequently, we have an option of having a graph with a white (actually light gray) background, You can choose to create both graphs if you wish. In the future, I would like add the possibility of a custom color graph. That would have new windows popping up from the basic window, something I want to try coding. Like the situation with the sensor widgets, check boxes might seem to be more efficient, bur radio buttons work better with the script making the measurements.</div>
<div style="margin-bottom: 0.1in;">The width of the graph is hard-coded to 600 pixels, but the height is programmable with the slider control. You can choose values from 100 to 400 pixels in increments of 100. A shorter graph is useful when the variation in the measurement values is small (nearly a straight, horizontal line). I have seen where RRDtool actually repeats values on the Y axis if the graph height is large and there is a small variation in measurement values. RRDtool selects the values on the Y axis, not the programmer.</div>
<div style="margin-bottom: 0.1in;">Next, we have the number of measurements and the interval between measurements. The smallest interval being one minute.</div>
<div style="margin-bottom: 0.1in;">Finally, we come to the matter of file names. As of now (meaning I may alter this in the future), the directory name is hard-coded in the script. I have a directory for all temperature measurements, but make up a new sub-directory, under that, based on the date (for example: 2013_10_25 for Oct. 25, 2013). The file name asked for by the widget is a base name without extension. Depending on the number of sensors used, and the number of graphs generated, we will make three to five files for each run of the script. The measurements used for the graph are stored in files with an .rrd extension - one file for each sensor. There is a .png file for each graph (one for black background, one for white). Finally, there is a .txt file generated to store all of the results, along with the measurement times, in an easily read form (the .rrd files are not easily read). This .txt file is another feature that is new with this version. If, for example, the base file name is rodger and we were to use both sensors, and generate both graphs, we would generate the following five files: rodger.txt, rodger_bread.rrd, rodger_cable.rrd, rodger_black.prn, and rodger_white.prn.</div>
<div style="margin-bottom: 0.1in;">The check box to the left of the file name is to protect the files from being overwritten if they already exist. It looks in the directory with the current date. Putting a check mark in the box allows the files to be overwritten.</div>
<div style="margin-bottom: 0.1in;">Let's put some values into the entry boxes but we'll make errors in all of the boxes:</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7kvbRjC_QVkfCvV2S9TXDpdEV0NqsbYBufhLthcJS4Htu2_I3ZmaNrrZXghXRD7u2sAfx0D1Fteaioed2J7gTG3THXSo6_u4pLSp8OXkK72Hhd_wXhQJuOUBPvyjQ6vfJocPbAQjhBIu6/s1440/GUI+For+Graph+Temperature+2.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7kvbRjC_QVkfCvV2S9TXDpdEV0NqsbYBufhLthcJS4Htu2_I3ZmaNrrZXghXRD7u2sAfx0D1Fteaioed2J7gTG3THXSo6_u4pLSp8OXkK72Hhd_wXhQJuOUBPvyjQ6vfJocPbAQjhBIu6/s576/GUI+For+Graph+Temperature+2.bmp" /><div class = "caption"><i>Result Of Pressing Continue If There Are Entry Errors</i></div></a></div>
<div style="margin-bottom: 0.1in;">After pressing the "Continue" button, the red error messages show up to the right of the entry boxes. The legend and comment boxes have non-escaped colons and the title has a non-escaped space. The measurement interval can not be zero (the number of measurements will give the same error if they total to zero). The error message will appear if a non-numeric character appears in the number of measurements or any of the measurement interval boxes. </div>
<div style="margin-bottom: 0in;">There are three possible error messages that can appear to the right of "Base Filename". They are:</div>
<UL>
<lI>Only numbers, letters, and underscore</LI>
<LI>Will overwrite existing file ("Allow File Overwrite" not checked</LI>
<LI>Must enter a file name (if you leave the box empty)</LI>
</ul>
<div style="margin-bottom: 0.1in;">Once all of the corrections have been made, hitting the "Continue" button will kill the window and allow the program that makes and graph temperature measurements to proceed. If you hit the "Quit" button the window closes and the calling script terminates.</div>
<div style="margin-bottom: 0.1in;">One other action happens before the window closes. All of the parameters entered in the window widgets are saved into a configuration file. The next time the program is run, all of the parameters are loaded into the window rather than the default values. This should save a lot of time if the same run is repeated or only a few changes are made. If a lot of changes are to be made a press of the "Default" button will bring up all of the default values.</div>
<div style="margin-bottom: 0.1in;">Let's do an actual run. The cable sensor is placed into a 12oz. glass of hot tap water and allowed to cool to ambient temperature. Here is the window:</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4kxORq9CgOwqCwe-EDZVUxsCX6t5xB7OO0AD3_FRM1N8hSysmXvTDUmU9rEpMm3o8GJBEHHfeyp2ScIlDJeuTN-15b5GvkCEordtlsjaJH7Nv1hR72V6qQrkTyjhep723O9hsgapUZidW/s1400/GUI+For+Graph+TemperatureFinal.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4kxORq9CgOwqCwe-EDZVUxsCX6t5xB7OO0AD3_FRM1N8hSysmXvTDUmU9rEpMm3o8GJBEHHfeyp2ScIlDJeuTN-15b5GvkCEordtlsjaJH7Nv1hR72V6qQrkTyjhep723O9hsgapUZidW/s576/GUI+For+Graph+TemperatureFinal.bmp" /><div class = "caption"><i>Window For Actual Run</i></div></a></div>
<div style="margin-bottom: 0.1in;">After pressing the "Continue" button the window closes and you see the terminal window:</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAiOjo41G1PXgSn6eZkmUifarxQyahWR8zwcjkjMNx-IAemvuMnGT3HOTnYULIeYnYxlJBgS46V3NItEDufL2EurkHyvcxcNLaNF0qd1buOxz5tSS-L2J5MakTQwvoFJvpZilqJPSIfBW6/s1243/RunningGraphTempWithGUI.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAiOjo41G1PXgSn6eZkmUifarxQyahWR8zwcjkjMNx-IAemvuMnGT3HOTnYULIeYnYxlJBgS46V3NItEDufL2EurkHyvcxcNLaNF0qd1buOxz5tSS-L2J5MakTQwvoFJvpZilqJPSIfBW6/s580/RunningGraphTempWithGUI.bmp" /><div class = "caption"><i>Terminal Window After a Few Measurements</i></div></a></div>
<div style="margin-bottom: 0.1in;">The terminal window shows the parameters chosen on the GUI. It gives you a last look at your selections. If you decide you wanted something else, simply hit Ctrl C to terminate the script. A careful reader will notice the parameters on the terminal screen do not match the parameters chosen in the window above. That is because I forgot to save the screen shot, so two different runs are represented. </div>
<div style="margin-bottom: 0.1in;">Below the parameters it says that the 1-wire modules had to be loaded. They are not loaded upon boot-up, so every time the Pi is powered up, or rebooted, the 1-wire modules must be loaded. The script checks to see if the modules are loaded, and, if not, loads them. Subsequent runs of the script will not need to load the modules if power stays applied and the Pi is not rebooted. Next, the script displays when the first measurements will be made. Recall that measurements are synchronized with the measurement interval. Since one minute was selected, we wait for the seconds to be 00. Next, we see the display of several measurements showing the day of the week, date and time, sensor, and the temperature as measured. The measurement results, along with time and sensor, are also displayed on my 16 character by two line Led Display. </div>
<div style="margin-bottom: 0.1in;">After all of the measurements have been made, as stipulated by the value in "Number Of Measurements", the script will stop. If you wish to stop the script prematurely, you can simply issue a Ctrl C or press the switch on the breadboard.</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5rkdGExoCaX29L4io8I6gfl8tQHa9Zidki4zlMainjJPnc9s_ISnOoSotEwqJHYugoSgz9eyQ4m7jNndWVtlH4JfOjizjNdiEXbLvfa6cqBquEmtTL-Zty2A7jI0XEBjUO6w4CROquPWI/s1243/screen2.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5rkdGExoCaX29L4io8I6gfl8tQHa9Zidki4zlMainjJPnc9s_ISnOoSotEwqJHYugoSgz9eyQ4m7jNndWVtlH4JfOjizjNdiEXbLvfa6cqBquEmtTL-Zty2A7jI0XEBjUO6w4CROquPWI/s580/screen2.JPG" /><div class = "caption"><i>Terminal Window At The End Of The Run</i></div></a></div>
<div style="margin-bottom: 0.1in;">Once the script is terminated, the terminal display looks similar to the figure above. This information is from yet another run. I did not coordinate that aspect of this post very well. You see the last of the measurements followed by a salutation and the reporting of the fact that there were no glitches. </div>
<div style="margin-bottom: 0.1in;">Originally, I had problems with measurement failures where the device file could not be read. I call that a glitch and keep track of the number of glitches for the entire run. My solution to recover from these glitches is to unload and reload the 1-wire modules. For every glitch, I only unload and reload the modules a maximum of three times. If there is no recovery after the tree tries, I stop the script and report a message. This problem has not reoccurred, I have not seen any glitches for a long time. </div>
<div style="margin-bottom: 0.1in;">The start time and stop time, are followed by long numbers. These numbers are the number of seconds since January 1, 1970. This is how RDTool records numbers in the .rrd files. If you want the time on the graph to be correct, you must apply these long numbers to the measurements. I report those numbers at the end here in case you wish to investigate the .rrd files. The information in the .rrd files look like gibberish if viewed with a text editor. You have to issue a RRDtool command to see the contents of these files. For more information see my post <a href="http://thepiandi.blogspot.com/2013/09/rrdtool-for-dummies-like-me.html">"RRDtool For Dummies Like Me"</a> under the topic "What Measurement Values Go Into the Database".</div>
<div style="margin-bottom: 0in;">Let's look at the code. The code is divided into two scripts, one for the GUI and the other for the main program that makes, graphs, and records the temperature measurements. The reason for a separate script for the GUI was to minimize changes to the main script. The main script is derived from the code shown in my blog entry, <a href="http://thepiandi.blogspot.com/2013/10/graphing-real-temperature-data-using.html". >"Graphing Real Temperature Data Using RRDtool and PyRRD". </a>The code for the GUI was developed independently, and has test code at the bottom so it can be run by itself, to check its operation. The GUI script was made a callable module by saving it as a .pyc file. The first 425 lines of the GUI code becomes a single function, guiwindow(). All of the parameters collected in the window are passed to the main script by line 103 of the main script: </div>
<div style="margin-bottom: 0.1in;"> <b>variable_list = guiwindow()</b></div>
<div style="margin-bottom: 0.1in;"><h3>Code For the GUI Window:</h3></div>
<script src="https://gist.github.com/RaspPiGuy/7075067.js"></script>
<div style="margin-bottom: 0.1in;">I know it's a rather long script (another reason for making it separate from the main script), but a lot goes on here. Each element of the window (widgets) must be defined. Some of the widgets, when clicked on by the user, spurn actions. These actions must be defined. A lot of code is devoted to making the appearance correct. Placement of widgets is somewhat of a challenge. As in most GUI applications, user inputs are checked to make sure required parameters are not missed, or errors made. The operator is made aware of these errors by messages so he knows what to correct. The error checking requires a lot of code. Just look at the function proceed(). Most of the widgets have error messages included in their definations.</div>
<div style="margin-bottom: 0.1in;">The development of the GUI is done using a module called Tkinter. It is probably available for all, common, Linux distributions for the Pi. I have developed all of my code using Python 2.7 so my line to import Tkinter is: "from <b>Tkinter</b> import *". In Python 3.x, that line would be "from <b>tkinter</b> import *". Tkinter is not just for Python, and not just for Linux. </div>
<div style="margin-bottom: 0.1in;">So, how does one get started developing GUIs for their Raspberry Pi projects? There are many references, including <a href="http://docs.python.org/2/library/tkinter.html#module-Tkinter">"The Python Library Reference"</a>. This document points you to other sources, including <a href="https://wiki.python.org/moin/TkInter">the Python Wiki,</a> a source with even more sources. One source you need to have available, constantly, is <a href="http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html">"Tkinter 8.5 Reference: a GUI for Python"</a> from the Computer Center of New Mexico Tech. You need this for no other reason then getting the syntax correct. It is really a great asset to GUI development. Another good source of help is my code above, and code of others, for you to see practical examples. There are even YouTube videos with Tkinter tutorials. There is a ton of stuff out there on the net on Tkinter.</div>
<div style="margin-bottom: 0.1in;">There are a few other items of interest in this script. Note the use of the Subprocess module in the function "getdirectory()". This is a way of issuing the Linux Ls command from Python. Here, Ls is used to see if a directory has been previously made. If it does not exist, the function makes the directory. Another cool thing is what happens, after the user presses "Continue" and the inputs have been found to contain no errors. Before the window closes and operation passed to the main program, all of the user's input gets saved to a file. When the window is opened again, the information in this file populates the widgets. This is done using a module called Pickle (actually cPickle. A version developed using C that runs faster than Pickle). Check it out, Pickle is a very efficient way to do the job and saves you from writing many lines of code. </div>
<div style="margin-bottom: 0.1in;"><h3>Main Script For Making, Graphing, and Recording Temperature Measurements:</h3></div>
<script src="https://gist.github.com/RaspPiGuy/7075006.js"></script>
<div style="margin-bottom: 0.1in;">Since this code for the main script was discussed in my earlier post, I'm not going to say much about it. One element I added is saving the results to a text file. I discussed this earlier in the post. Lines 281 - 288, 312 - 319, and 327 - 334 handle this task. The directory and file name come from the GUI window.</div>
<div style="margin-bottom: 0.1in;">I almost forgot, here are the two graphs:</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnVviBp7e0kzGFL_BL8mL5xqpo5OkassqevjNm7RgIh_77ArwUvZhNvqqrjnqhMAecdGTwGNiqprlrKjjkXVIo92nDYY5cHni5FFOTObLpI5_s2QUYkocQ4zEI7uOZERT_0zwVqVqxMsW9/s1400/TapWaterCooling_black.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnVviBp7e0kzGFL_BL8mL5xqpo5OkassqevjNm7RgIh_77ArwUvZhNvqqrjnqhMAecdGTwGNiqprlrKjjkXVIo92nDYY5cHni5FFOTObLpI5_s2QUYkocQ4zEI7uOZERT_0zwVqVqxMsW9/s560/TapWaterCooling_black.png" /><div class = "caption"><i>Graph Corresponding To Window Above</i></div></a></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFXx05QVOUzg_kwfpsGDdviqpH-Lt2SX-UeSMzy3CEgEoL1tnqDH0Lr4StlKkBxuspHQED-t_U8VwzuWbR-QSwF4sN8rjLQulawXm-Ni3EaaeJ2GJEb2OKC7Xkl6J1R2JGyocGJ1OkFf0W/s1400/TapWaterCooling_white.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFXx05QVOUzg_kwfpsGDdviqpH-Lt2SX-UeSMzy3CEgEoL1tnqDH0Lr4StlKkBxuspHQED-t_U8VwzuWbR-QSwF4sN8rjLQulawXm-Ni3EaaeJ2GJEb2OKC7Xkl6J1R2JGyocGJ1OkFf0W/s560/TapWaterCooling_white.png" /><div class = "caption"><i>This Graph Is Better For Printing - It Saves Ink</i></div></a></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
<div style="margin-bottom: 0.1in;"></div>
</span>Martyhttp://www.blogger.com/profile/05173882240434059847noreply@blogger.com0