Team:TU-Munich/Results/How To
From 2013.igem.org
(→Slideshow) |
PSchneider (Talk | contribs) m (→Code) |
||
(6 intermediate revisions not shown) | |||
Line 74: | Line 74: | ||
</html> | </html> | ||
- | ==Generation of | + | ==Generation of Rotating Protein Structures== |
- | + | Animated gifs of rotating protein structures have been used for some time in the iGEM competition. Here we present an easy to reproduce tutorial for iGEMers which are interested in similar images. | |
- | *If there is no PDB file | + | *If there is no PDB file available for your protein of interest, you can use a homology search to find the most homologous structure. A good homology search tool is [http://toolkit.tuebingen.mpg.de/hhpred HHpred]. |
- | *The entry for the best matching structure was used for the figure. If it is only a homologous structure please cite this together with the homology when presenting the resulting | + | *The entry for the best matching structure was used for the figure. If it is only a homologous structure please cite this together with the homology when presenting the resulting image. |
- | *You can save the PDB file of the homologous structure on your computer | + | *You can save the PDB file of the homologous structure on your computer. |
*If you do not have [http://www.pymol.org/ PyMol] (freeware) installed on your computer download and install it. | *If you do not have [http://www.pymol.org/ PyMol] (freeware) installed on your computer download and install it. | ||
- | *Start PyMol software and open the PDB | + | *Start PyMol software and open the PDB file by clicking File -> Open. |
- | *The following approach was adapted from a PyMol | + | *The following approach was adapted from a PyMol tutorial [[http://ihome.cuhk.edu.hk/~b102142/pymol/pymol_tutorial.html Wong]]. |
*The following commands were entered into the command line: | *The following commands were entered into the command line: | ||
<code> | <code> | ||
Line 98: | Line 98: | ||
PyMOL> mpng frame<br> | PyMOL> mpng frame<br> | ||
</code> | </code> | ||
- | * | + | *Afterwards the *.png files were automatically converted to *.tif files using [http://www.xnview.com/de/xnconvert/ XnConvert]. |
- | *The program [http://www.animake.de/gif-animation.htm Animake] was used to generate the annimated | + | *The program [http://www.animake.de/gif-animation.htm Animake] was used to generate the annimated gifs. |
**The Animake software was started | **The Animake software was started | ||
- | **A new working folder was generated (File>New) and the *. | + | **A new working folder was generated (File -> New) and the *.tif files were imported (Edit -> Import_from_file) |
- | **The background was set to white ( | + | **The background was set to white (Animation -> Settings) |
- | **The range of colors was set to 256 (Edit>Select_all and Edit>Change_Color) | + | **The range of colors was set to 256 (Edit -> Select_all and Edit -> Change_Color) |
- | **The size of the file has to be reduced in order to be able to upload it on the iGEM wiki. This can be done by clicking Edit>Change_size. We suggest a size of 320x240 px or even | + | **The size of the file has to be reduced in order to be able to upload it on the iGEM wiki. This can be done by clicking Edit -> Change_size. We suggest a size of 320x240 px or even smaller if the resulting gif becomes to big. |
- | **Finally the | + | **Finally the animated gif can be saved in the program format (.abp) and as gif (File -> Save_as) |
**If you have problems to upload the file on the iGEM server you may try a reduced size (e.g. 300x225 px) | **If you have problems to upload the file on the iGEM server you may try a reduced size (e.g. 300x225 px) | ||
<center>This is how your protein of interest could look like:</center> | <center>This is how your protein of interest could look like:</center> | ||
- | [[File:TUM13_Annimated_test.gif|thumb|center|320px|'''Figure | + | [[File:TUM13_Annimated_test.gif|thumb|center|320px|'''Figure 2:''' Protein]] |
==Setting up a basic Arduino measuring device== | ==Setting up a basic Arduino measuring device== | ||
Line 115: | Line 115: | ||
[[File:TUM13_Arduino_Assembly_Animation.gif|thumb|left|400px|'''Figure 3:''' Assembly Order]] | [[File:TUM13_Arduino_Assembly_Animation.gif|thumb|left|400px|'''Figure 3:''' Assembly Order]] | ||
- | Since the Arduino Due was released in autumn 2012, this is the first | + | Since the Arduino Due was released in autumn 2012, this is the first iGEM year this '''very powerful''' device can be used. We found it a useful '''supervising tool''' for short and long-term experiments. It can be used in as well as outside the lab. The improvements that were made from Uno to Due are considerable. |
- | It is capable of handling many things at once, such as a WiFi | + | It is capable of handling many things at once, such as a WiFi shield, a display, a SD-Card and multiple sensors. |
- | At this point the Uno | + | At this point the Uno did not match up any longer. |
- | To establish the usage of Arduino in | + | To establish the usage of Arduino in iGEM even more we want to share our experiences and help you building up a '''basic device''' that can '''collect''' and '''view sensor data''' on its '''display''' and '''upload''' them to a server. |
===Part Description=== | ===Part Description=== | ||
Line 132: | Line 132: | ||
<li><img src="https://static.igem.org/mediawiki/2013/9/99/Arduino_Tsl2561.png" alt="Figure 8: TSL2561 light sensor" /></li> | <li><img src="https://static.igem.org/mediawiki/2013/9/99/Arduino_Tsl2561.png" alt="Figure 8: TSL2561 light sensor" /></li> | ||
<li><img src="https://static.igem.org/mediawiki/2013/a/a5/Arduino_Tsl2561_Curve.png" alt="Figure 9: TSL2561 absorption curve" /></li> | <li><img src="https://static.igem.org/mediawiki/2013/a/a5/Arduino_Tsl2561_Curve.png" alt="Figure 9: TSL2561 absorption curve" /></li> | ||
- | <li><img src="https://static.igem.org/mediawiki/2013/3/3d/Arduino_Watersensor.png" alt="Figure 10: | + | <li><img src="https://static.igem.org/mediawiki/2013/3/3d/Arduino_Watersensor.png" alt="Figure 10: Water sensor" /></li> |
</ul> | </ul> | ||
</div> | </div> | ||
Line 138: | Line 138: | ||
====Arduino Due==== | ====Arduino Due==== | ||
- | The Arduino Due is the most powerful Arduino board. | + | The Arduino Due is the most powerful Arduino board. Its underlying 32bit-processor is the Atmel SAM3X8E. |
- | Contrary to the other boards which run at 5V, a power supply of 3.3V is | + | Contrary to the other boards which run at 5V, a power supply of 3.3V is sufficient. |
It was released in October 2012. | It was released in October 2012. | ||
- | Data: | + | '''Data:''' |
84 Mhz CPU Clock | 84 Mhz CPU Clock | ||
Line 155: | Line 155: | ||
The Arduino WiFi Shield is an attachable shield that provides Wireless LAN 802.11b/g to the Arduino. | The Arduino WiFi Shield is an attachable shield that provides Wireless LAN 802.11b/g to the Arduino. | ||
It scans and connects to networks and opens TCP and UDP sockets for data transfer. It also supports WEP and WPA2 encryption. It was released in August 2012. | It scans and connects to networks and opens TCP and UDP sockets for data transfer. It also supports WEP and WPA2 encryption. It was released in August 2012. | ||
- | The WiFi Shield is fully supported by the Arduino Due and Arduino supplies a suitable stock WiFi | + | The WiFi Shield is fully supported by the Arduino Due and Arduino supplies a suitable stock WiFi library. |
There is also an on-board SD-card socket to store received data. | There is also an on-board SD-card socket to store received data. | ||
As the SD-card is accessible separately, it can also be used as a storage for any data generated by the Arduino. | As the SD-card is accessible separately, it can also be used as a storage for any data generated by the Arduino. | ||
Line 171: | Line 171: | ||
5V | 5V | ||
- | ====Watterott | + | ====Watterott Mega MSD-Shield==== |
- | The | + | The Mega MSD-Shield was designed by Watterott and consists of a couple of components. |
- | The components are one real time clock, one SD-card socket (we | + | The components are one real time clock, one SD-card socket (we will not use), a small battery and a socket for a touch display. |
To get it ready to run, the shield must be assembled. The stackable headers and the clock's quartz must be soldered to the board and the battery must be inserted. | To get it ready to run, the shield must be assembled. The stackable headers and the clock's quartz must be soldered to the board and the battery must be inserted. | ||
- | Unluckily the | + | Unluckily the Mega MSD-Shield and therefore also the MI0283QT-9 touch display don't come with a working library for the Arduino Due. The existing library only supports all boards up to the Arduino Uno. |
- | Therefore all libraries | + | Therefore all libraries had to be rewritten. |
- | The touch display and the SD-card | + | The touch display and the SD-card slot communicate with the Arduino Due via SPI/ICSP. The real time clock transmits its data via I²C. |
'''Pin usage:''' | '''Pin usage:''' | ||
Line 197: | Line 197: | ||
The MI0283QT-9 is a multicolor touch display. It comes already attached to a board, where only the pin headers are left to be soldered. | The MI0283QT-9 is a multicolor touch display. It comes already attached to a board, where only the pin headers are left to be soldered. | ||
- | Once assembled it can easily be plugged into the | + | Once assembled it can easily be plugged into the Mega MSD-Shield. It has an on-board touch controller (TI ADS7846). |
The display size is 2.83"(43.2 x 57.6mm) with a resolution of 240x320. It supports 262k colors. | The display size is 2.83"(43.2 x 57.6mm) with a resolution of 240x320. It supports 262k colors. | ||
- | The pin usage is already considered in the | + | The pin usage is already considered in the Mega MSD-Shield description. |
- | ====Light | + | ====Light Sensor TSL2561==== |
The light sensor is a small, so called, breakout board. It is usually connected by wires instead of directly plugged into the Arduino's headers. | The light sensor is a small, so called, breakout board. It is usually connected by wires instead of directly plugged into the Arduino's headers. | ||
- | The light sensor has two photo | + | The light sensor has two photo diodes on-board that measure visible and infrared light. Similar to the RTC, the TSL2561 is addressed via I²C. |
Once you get the I²C library working on your Arduino Due working it takes only little effort to integrate additional I²C devices. | Once you get the I²C library working on your Arduino Due working it takes only little effort to integrate additional I²C devices. | ||
Just very few lines of the library have to be rewritten here. | Just very few lines of the library have to be rewritten here. | ||
- | The photo | + | The photo diodes can be addressed separately or both at one. Their output is already converted to Lux. |
- | ''' | + | '''Pin usage:''' |
Pin 20 TSL2561 I²C SDA (Serial Data Line) | Pin 20 TSL2561 I²C SDA (Serial Data Line) | ||
Line 216: | Line 216: | ||
3.3V | 3.3V | ||
- | ====Temperature | + | ====Temperature Sensor DS18B20==== |
- | The temperature sensor is embedded into a water proof cable. It is addressed via a | + | The temperature sensor is embedded into a water proof cable. It is addressed via a OneWire interface. |
- | The provided data are digital raw data, which need to be converted into | + | The provided data are digital raw data, which need to be converted into degree Celsius. Information about the conversion are given by the manufacturer. |
- | Similar to the I²C (TwoWire) bus, you only have to get the | + | Similar to the I²C (TwoWire) bus, you only have to get the OneWire interface working once. After that, you can easily set up more OneWire devices. |
Again, just very few lines of the library have to be rewritten. | Again, just very few lines of the library have to be rewritten. | ||
- | ''' | + | '''Pin usage:''' |
Pin 14 One-Wire DS18B20 (pin was randomly chosen) | Pin 14 One-Wire DS18B20 (pin was randomly chosen) | ||
Line 229: | Line 229: | ||
Pin 3.3V | Pin 3.3V | ||
- | ====Water | + | ====Water Sensor==== |
Setting up the water sensor is very easy. If and how much water the sensor registered can be measured via an analog pin. | Setting up the water sensor is very easy. If and how much water the sensor registered can be measured via an analog pin. | ||
Line 238: | Line 238: | ||
gnd | gnd | ||
3.3V | 3.3V | ||
- | |||
- | |||
- | |||
- | |||
- | |||
===Tools=== | ===Tools=== | ||
Line 252: | Line 247: | ||
- | Keep everything clear during your assembly. If you have different colored linking cables, always try to use the same color code. | + | Keep everything clear during your assembly. If you have different colored linking cables, always try to use the same color code (e.g. red cable for 3.3V etc.) otherwise troubleshooting can get nasty. |
- | + | ||
All '''steps''' you need to follow building up your own Arduino measuring device are '''explained below''' in the '''slide show''' and the image descriptions. | All '''steps''' you need to follow building up your own Arduino measuring device are '''explained below''' in the '''slide show''' and the image descriptions. | ||
Line 261: | Line 255: | ||
<ul class="bxgallery"> | <ul class="bxgallery"> | ||
<li><img src=" | <li><img src=" | ||
- | https://static.igem.org/mediawiki/2013/thumb/d/d7/TUM13_Arduiono_Assembly_1.png/350px-TUM13_Arduiono_Assembly_1.png" alt="Figure 11: | + | https://static.igem.org/mediawiki/2013/thumb/d/d7/TUM13_Arduiono_Assembly_1.png/350px-TUM13_Arduiono_Assembly_1.png" alt="Figure 11: Place your Arduino Due on your desk"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/c/c4/TUM13_Arduiono_Assembly_2.png/350px-TUM13_Arduiono_Assembly_2.png" alt="Figure 12: | + | https://static.igem.org/mediawiki/2013/thumb/c/c4/TUM13_Arduiono_Assembly_2.png/350px-TUM13_Arduiono_Assembly_2.png" alt="Figure 12: Connect ground and 3.3V to two different lines of you breadboard"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/2/21/TUM13_Arduiono_Assembly_3.png/350px-TUM13_Arduiono_Assembly_3.png" alt="Figure 13: | + | https://static.igem.org/mediawiki/2013/thumb/2/21/TUM13_Arduiono_Assembly_3.png/350px-TUM13_Arduiono_Assembly_3.png" alt="Figure 13: Connect the light sensor's ground and the 3.3V line"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/9/9b/TUM13_Arduiono_Assembly_4.png/350px-TUM13_Arduiono_Assembly_4.png" alt="Figure 14: | + | https://static.igem.org/mediawiki/2013/thumb/9/9b/TUM13_Arduiono_Assembly_4.png/350px-TUM13_Arduiono_Assembly_4.png" alt="Figure 14: Connect the sda line of your light sensor to pin 20 and scl to pin 21"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/9/9c/TUM13_Arduiono_Assembly_5.png/350px-TUM13_Arduiono_Assembly_5.png" alt="Figure 15: | + | https://static.igem.org/mediawiki/2013/thumb/9/9c/TUM13_Arduiono_Assembly_5.png/350px-TUM13_Arduiono_Assembly_5.png" alt="Figure 15: Connect the temperature sensor's ground and the 3.3V line"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/f/f8/TUM13_Arduiono_Assembly_6.png/350px-TUM13_Arduiono_Assembly_6.png" alt="Figure 16: | + | https://static.igem.org/mediawiki/2013/thumb/f/f8/TUM13_Arduiono_Assembly_6.png/350px-TUM13_Arduiono_Assembly_6.png" alt="Figure 16: Connect the signal line of your temp sensor via the breadbroad to pin 14" /></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/8/83/TUM13_Arduiono_Assembly_7.png/350px-TUM13_Arduiono_Assembly_7.png" alt="Figure 17: | + | https://static.igem.org/mediawiki/2013/thumb/8/83/TUM13_Arduiono_Assembly_7.png/350px-TUM13_Arduiono_Assembly_7.png" alt="Figure 17: Place a ~50kOhm resistor between the 3.3V line and the temps sensor's signal line on your breadboard" /></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/b/b0/TUM13_Arduiono_Assembly_8.png/350px-TUM13_Arduiono_Assembly_8.png" alt="Figure 18: | + | https://static.igem.org/mediawiki/2013/thumb/b/b0/TUM13_Arduiono_Assembly_8.png/350px-TUM13_Arduiono_Assembly_8.png" alt="Figure 18: Connect the water sensor to the ground and 3.3V line"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/e/e4/TUM13_Arduiono_Assembly_9.png/350px-TUM13_Arduiono_Assembly_9.png" alt="Figure 19: | + | https://static.igem.org/mediawiki/2013/thumb/e/e4/TUM13_Arduiono_Assembly_9.png/350px-TUM13_Arduiono_Assembly_9.png" alt="Figure 19: Connect the signal line of your water sensor to pin A5"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/8/86/TUM13_Arduiono_Assembly_10.png/350px-TUM13_Arduiono_Assembly_10.png" alt="Figure 20: | + | https://static.igem.org/mediawiki/2013/thumb/8/86/TUM13_Arduiono_Assembly_10.png/350px-TUM13_Arduiono_Assembly_10.png" alt="Figure 20: Voila! You are done with the basic connection of your three sensors. The next steps explain how to connect the WiFi shield, the msd shield and the display. You can connect all the sensors to the shield's and header's pins the same way, you connected them to the Arduino Due"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/d/d0/TUM13_Arduiono_Assembly_11.png/350px-TUM13_Arduiono_Assembly_11.png" alt="Figure 21: | + | https://static.igem.org/mediawiki/2013/thumb/d/d0/TUM13_Arduiono_Assembly_11.png/350px-TUM13_Arduiono_Assembly_11.png" alt="Figure 21: First solder a short copper cable to the msd shield, connecting its pin 25 to pin 7"/></li><li><img src=" |
https://static.igem.org/mediawiki/2013/thumb/1/18/TUM13_Arduiono_Assembly_12.png/350px-TUM13_Arduiono_Assembly_12.png" alt="Figure 22: Then bend pin 7 and pin 4, so they don't connect to the WiFi shield's pins. Pin 4 would be a double usage of the msd shield's and the wifi shield's sd card. Pin 7 (lcd slave select) interferes with the wifi handshake pin"/></li><li><img src=" | https://static.igem.org/mediawiki/2013/thumb/1/18/TUM13_Arduiono_Assembly_12.png/350px-TUM13_Arduiono_Assembly_12.png" alt="Figure 22: Then bend pin 7 and pin 4, so they don't connect to the WiFi shield's pins. Pin 4 would be a double usage of the msd shield's and the wifi shield's sd card. Pin 7 (lcd slave select) interferes with the wifi handshake pin"/></li><li><img src=" | ||
https://static.igem.org/mediawiki/2013/thumb/9/99/TUM13_Arduiono_Assembly_13.png/350px-TUM13_Arduiono_Assembly_13.png" alt="Figure 23: This is just an explanation of how the shield's sub-devices are connected. A deeper understanding of the following diagrams goes along with a deeper understanding of the program's source code and the additional libraries. All shields are of course connected to the Arduino Due's ground and 3.3V line"/></li><li><img src=" | https://static.igem.org/mediawiki/2013/thumb/9/99/TUM13_Arduiono_Assembly_13.png/350px-TUM13_Arduiono_Assembly_13.png" alt="Figure 23: This is just an explanation of how the shield's sub-devices are connected. A deeper understanding of the following diagrams goes along with a deeper understanding of the program's source code and the additional libraries. All shields are of course connected to the Arduino Due's ground and 3.3V line"/></li><li><img src=" | ||
https://static.igem.org/mediawiki/2013/thumb/e/e8/TUM13_Arduiono_Assembly_14.png/350px-TUM13_Arduiono_Assembly_14.png" alt="Figure 24: The yellow link shows the spi interface between Arduino Due and the WiFi shield"/></li><li><img src=" | https://static.igem.org/mediawiki/2013/thumb/e/e8/TUM13_Arduiono_Assembly_14.png/350px-TUM13_Arduiono_Assembly_14.png" alt="Figure 24: The yellow link shows the spi interface between Arduino Due and the WiFi shield"/></li><li><img src=" | ||
- | https://static.igem.org/mediawiki/2013/thumb/d/d9/TUM13_Arduiono_Assembly_15.png/350px-TUM13_Arduiono_Assembly_15.png" alt="Figure 25: | + | https://static.igem.org/mediawiki/2013/thumb/d/d9/TUM13_Arduiono_Assembly_15.png/350px-TUM13_Arduiono_Assembly_15.png" alt="Figure 25: The thinner yellow lines are the WiFi handshake and the wifi slave select connections"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/d/d0/TUM13_Arduiono_Assembly_16.png/350px-TUM13_Arduiono_Assembly_16.png" alt="Figure 26: | + | https://static.igem.org/mediawiki/2013/thumb/d/d0/TUM13_Arduiono_Assembly_16.png/350px-TUM13_Arduiono_Assembly_16.png" alt="Figure 26: The blue link is the sd reader's slave select"/></li><li><img src=" |
https://static.igem.org/mediawiki/2013/thumb/6/6d/TUM13_Arduiono_Assembly_17.png/350px-TUM13_Arduiono_Assembly_17.png" | https://static.igem.org/mediawiki/2013/thumb/6/6d/TUM13_Arduiono_Assembly_17.png/350px-TUM13_Arduiono_Assembly_17.png" | ||
- | alt="Figure 27: | + | alt="Figure 27: The green link represents the connection to the real time clock"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/7/75/TUM13_Arduiono_Assembly_18.png/350px-TUM13_Arduiono_Assembly_18.png" alt="Figure 28: | + | https://static.igem.org/mediawiki/2013/thumb/7/75/TUM13_Arduiono_Assembly_18.png/350px-TUM13_Arduiono_Assembly_18.png" alt="Figure 28: The pink link represents the spi interface between the msd shield and the Arduino Due, required for the communication with the lcd and its touch functions (pins 50, 51 and pin 52)"/></li><li><img src=" |
- | https://static.igem.org/mediawiki/2013/thumb/4/4b/TUM13_Arduiono_Assembly_19.png/350px-TUM13_Arduiono_Assembly_19.png" alt="Figure 29: | + | https://static.igem.org/mediawiki/2013/thumb/4/4b/TUM13_Arduiono_Assembly_19.png/350px-TUM13_Arduiono_Assembly_19.png" alt="Figure 29: Lcd slave select, lcd reset and lcd LED"/></li><li><img src=" |
- | + | https://static.igem.org/mediawiki/2013/thumb/f/fd/TUM13_Arduiono_Assembly_20.png/350px-TUM13_Arduiono_Assembly_20.png" alt="Figure 30: Lcd's touch slave select"/></li> | |
- | https://static.igem.org/mediawiki/2013/thumb/f/fd/TUM13_Arduiono_Assembly_20.png/350px-TUM13_Arduiono_Assembly_20.png" alt="Figure 30: | + | |
<li><img src="https://static.igem.org/mediawiki/2013/thumb/5/5c/TUM13_Arduiono_Assembly_21.png/350px-TUM13_Arduiono_Assembly_21.png" alt="Figure 31: the power supply can be established with a 9V block battery"/></li> | <li><img src="https://static.igem.org/mediawiki/2013/thumb/5/5c/TUM13_Arduiono_Assembly_21.png/350px-TUM13_Arduiono_Assembly_21.png" alt="Figure 31: the power supply can be established with a 9V block battery"/></li> | ||
- | <li><img src="https://static.igem.org/mediawiki/2013/thumb/e/ef/TUM13_Arduiono_Assembly_22.png/350px-TUM13_Arduiono_Assembly_22.png" alt="Figure 32: | + | <li><img src="https://static.igem.org/mediawiki/2013/thumb/e/ef/TUM13_Arduiono_Assembly_22.png/350px-TUM13_Arduiono_Assembly_22.png" alt="Figure 32: At last: an overview"/></li> |
</ul> | </ul> | ||
Line 290: | Line 283: | ||
</html> | </html> | ||
[[File:TUM13_Arduino_in_action.gif|thumb|500px|left|'''Figure 33:''' Arduino in action]] | [[File:TUM13_Arduino_in_action.gif|thumb|500px|left|'''Figure 33:''' Arduino in action]] | ||
- | For more explaining photos visit our [[#Arduino_photo_gallery|photo | + | For more explaining photos visit our [[#Arduino_photo_gallery|photo gallery]]. On the left you see the Arduino as it boots up, connects to a WiFi hotspot and collects data. |
===Code=== | ===Code=== | ||
Line 296: | Line 289: | ||
We strongly recommend the usage of '''Microsoft Visual Studio''' with the '''"visual micro"''' plugin. Microsoft Intellisense helps you a lot, when you are unfamiliar with the manufacturer provided libraries (automatic code completion). In order to compile the code properly you need the latest beta version of [http://arduino.cc/en/Main/Software Arduino's software]. In the visual micro settings, choose the path to the Arduino IDE on your hard drive, also disable "Upload using programmer". In the settings of the Arduino IDE, select "use external software". | We strongly recommend the usage of '''Microsoft Visual Studio''' with the '''"visual micro"''' plugin. Microsoft Intellisense helps you a lot, when you are unfamiliar with the manufacturer provided libraries (automatic code completion). In order to compile the code properly you need the latest beta version of [http://arduino.cc/en/Main/Software Arduino's software]. In the visual micro settings, choose the path to the Arduino IDE on your hard drive, also disable "Upload using programmer". In the settings of the Arduino IDE, select "use external software". | ||
- | Now you are ready to start programming. | + | Now you are ready to start programming. Below we share our code, feel free to use, edit and play around with it! |
But '''wait''' first you need our '''[[#Libraries|libraries]]'''! They're exclusively '''fitted''' to the Arduino Due, mostly based on the existing manufacturer's libraries for the Arduino Uno. | But '''wait''' first you need our '''[[#Libraries|libraries]]'''! They're exclusively '''fitted''' to the Arduino Due, mostly based on the existing manufacturer's libraries for the Arduino Uno. | ||
- | + | Since Arduino released a new version of its IDE and software, and extended its support on the Arduino Due, we have rewritten our previews code. Both, the old and the new code can be found in our '''[https://github.com/VonAlphaBisZulu/IGEM_ARDUINO GitHub repo]'''. | |
+ | |||
+ | Assuming you followed our tutorial until here. | ||
Once you adapted the code to your WiFi and server settings and uploaded it to the Arduino it does the following: | Once you adapted the code to your WiFi and server settings and uploaded it to the Arduino it does the following: | ||
- | #it starts up and the '''screen''' | + | #it starts up and the '''screen''' stays black, but turns its lights on |
#if you have pressed the screen, the calibration process starts | #if you have pressed the screen, the calibration process starts | ||
#it '''searches for networks''' and displays the total number of found networks on its screen | #it '''searches for networks''' and displays the total number of found networks on its screen | ||
- | #it displays | + | #it displays some '''WiFi stations''' that were found |
#it tries to '''connect''' to the WiFi station you have set | #it tries to '''connect''' to the WiFi station you have set | ||
#if a connection was established it shows the '''Arduino's IP address''' and the SSID (name) of the WiFi it is connected to | #if a connection was established it shows the '''Arduino's IP address''' and the SSID (name) of the WiFi it is connected to | ||
#then it idles until you you press the screen | #then it idles until you you press the screen | ||
- | #after you pressed the screen it | + | #after you pressed the screen it jumps to the '''"loop"-section''' of the code |
#it continuously runs and displays: | #it continuously runs and displays: | ||
##the current '''time''' | ##the current '''time''' | ||
##the '''temperature''' | ##the '''temperature''' | ||
##the measured '''infrared''' and '''broadband light''' | ##the measured '''infrared''' and '''broadband light''' | ||
- | |||
##the '''coordinates''' of the point you '''pressed''' on the screen | ##the '''coordinates''' of the point you '''pressed''' on the screen | ||
- | #it builds up a '''connection to a server, calling a | + | #it builds up a '''connection to a server, calling a PHP script, passing on the collected data''' |
<nowiki> | <nowiki> | ||
#include "SPI.h" // SPI library (stock) | #include "SPI.h" // SPI library (stock) | ||
#include "Wire.h" // TwoWire library (stock) sda-scl | #include "Wire.h" // TwoWire library (stock) sda-scl | ||
- | #include " | + | #include "RTClib.h" // Real time clock library (original library, slightly rewritten to fit the Due) |
- | #include " | + | #include "SPI.h" |
- | #include " | + | #include "MI0283QT9Due.h" // LCD library (quite much had to be rewritten). Pins were changed, usage of Software SPI... quite a mess but it works great |
+ | #include "ADS7846Due.h" // Touch controller (same story as at the lcd library) | ||
#include "Adafruit_TSL2561.h" // light sensor library (had to be rewritten in some parts to fit the Due) functions were added to correct the lux-output that wasn't always correct with the stock library | #include "Adafruit_TSL2561.h" // light sensor library (had to be rewritten in some parts to fit the Due) functions were added to correct the lux-output that wasn't always correct with the stock library | ||
#include "OneWire.h" // OneWire (I don't know, but I guess it's the stock library) | #include "OneWire.h" // OneWire (I don't know, but I guess it's the stock library) | ||
Line 330: | Line 325: | ||
#include "WiFi.h" // (stock) | #include "WiFi.h" // (stock) | ||
#include "time.h" // standard C-time library | #include "time.h" // standard C-time library | ||
+ | #include "math.h" | ||
- | + | #define ledW (11) | |
- | + | #define ledR (12) | |
- | + | #define ledG (13) | |
- | + | #define Poti (A0) | |
- | + | #define Button (A1) | |
- | + | #define Temp (14) | |
- | + | #define Wat (A5) | |
- | + | ||
- | + | #define shift8to32(a,b,c,d) (d << 24) | (c << 16) | (b << 8) | a | |
- | + | #define shift8to16(a,b) (b << 8) | a | |
- | + | ||
- | + | ||
- | + | MI0283QT9 lcd; | |
- | + | ADS7846 tp; | |
- | + | RTC_DS1307 rtc; | |
- | + | OneWire tempsen(Temp); | |
- | + | Adafruit_TSL2561 lightsen(TSL2561_ADDR_FLOAT,12345); | |
- | + | File bitmap; | |
- | + | WiFiClient client(0); | |
- | + | ||
- | + | float valueWater=0, valueTemp=0, valueLight=0, valueLightIR=0; // sensor values (avaredged) | |
- | + | uint32_t valueTime=0,valueCounter[3]={0,0,0}; | |
- | + | uint16_t counter=1,potValue=0; // vlauecounter 0:Water 1:Temp 2:Light/IR | |
+ | uint8_t cursorY=1,cursorX=0; | ||
+ | bool buttonValue=0,logging=0,wifiConnection,mossstatus=0,firstreceive=1; | ||
+ | |||
+ | int waitForTap(){ | ||
+ | tp.service(); | ||
+ | while(tp.getPressure()==0) // Idle until the touchscreen is pressed to continue | ||
+ | { | ||
+ | delay(20); | ||
+ | tp.service(); | ||
+ | if(digitalRead(Button)==0) | ||
+ | return 1; | ||
+ | } | ||
+ | return 0; | ||
} | } | ||
- | void | + | void continueText(String drawtext, int cursY=cursorY-1, int cursX=cursorX,int maxlen=38){ |
- | { | + | maxlen=maxlen-cursX; |
- | + | ||
- | + | lcd.drawText(15+cursX*8,cursY*15,drawtext,1,COLOR_WHITE,COLOR_BLACK); | |
- | + | ||
+ | cursorX=drawtext.length()+1; | ||
} | } | ||
- | void | + | void drawText(String drawtext="", int cursY=cursorY,int maxlen=38){ |
+ | continueText(drawtext,cursY,0); | ||
+ | cursorY=cursY+1; | ||
+ | } | ||
+ | |||
+ | void OpenBMPFile(char *file, int16_t x, int16_t y) | ||
{ | { | ||
- | + | uint8_t pad; | |
- | + | uint8_t buf[54]; //read buf (min. size = sizeof(BMP_DIPHeader)) | |
- | + | int16_t width, height, w, h; | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | if(!SD.exists(file)) | |
- | + | { | |
- | + | Serial.println(String(file)+"not found"); | |
- | + | return; | |
- | + | } | |
- | + | else | |
- | + | bitmap = SD.open(file, FILE_READ); | |
- | + | if(!bitmap.available()) | |
- | + | { | |
- | + | Serial.println("not reading image file"); | |
- | + | return; | |
- | + | } | |
+ | else | ||
+ | Serial.println("reading image file"); | ||
+ | |||
+ | //BMP Header | ||
+ | for(int i=0;i<14;i++) | ||
+ | { | ||
+ | buf[i]=bitmap.read(); | ||
+ | } | ||
+ | |||
+ | if((buf[0] == 'B') && (buf[1] == 'M') && (buf[10] == 54)) | ||
+ | { | ||
+ | Serial.println("Bitmap recognized"); | ||
+ | //BMP DIP-Header | ||
+ | for(int i=14;i<54;i++) | ||
+ | buf[i]=bitmap.read(); | ||
+ | if( | ||
+ | Serial.println(shift8to32(buf[14],buf[15],buf[16],buf[17]))&& // size | ||
+ | Serial.println(shift8to16(buf[28],buf[29]))&& // bitspp | ||
+ | Serial.println(shift8to32(buf[30],buf[31],buf[32],buf[33]))) // compress | ||
+ | { | ||
+ | Serial.println("DIP recognized"); | ||
+ | //BMP data (1. pixel = bottom left) | ||
+ | width = shift8to32(buf[18],buf[19],buf[20],buf[21]); // width | ||
+ | height = shift8to32(buf[22],buf[23],buf[24],buf[25]); // height | ||
+ | pad = width % 4; //padding (line is multiply of 4) | ||
+ | Serial.println("printing"); | ||
+ | if((x+width) <= lcd.getWidth() && (y+height) <= lcd.getHeight()) | ||
+ | { | ||
+ | lcd.setArea(x, y, x+width-1, y+height-1); | ||
+ | for(h=(y+height-1); h >= y; h--) //for every line | ||
+ | { | ||
+ | uint8_t pix[320][3]; | ||
+ | bitmap.read(pix,width*3); | ||
+ | for(w=0; w < width; w++) //for every pixel in line | ||
+ | { | ||
+ | lcd.drawPixel(x+w, h, RGB(pix[w][2],pix[w][1],pix[w][0])); | ||
+ | } | ||
+ | if(pad) | ||
+ | { | ||
+ | bitmap.read(pix, pad); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | lcd.drawTextPGM(x, y, PSTR("Pic out of screen!"), 1, RGB(0,0,0), RGB(255,255,255)); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | bitmap.close(); | ||
} | } | ||
- | void | + | void initDisplay() |
{ | { | ||
- | + | lcd.init(); | |
- | + | lcd.setOrientation(180); | |
- | + | lcd.led(100); | |
- | + | lcd.clear(COLOR_BLACK); | |
} | } | ||
- | void | + | void initSD(){ |
- | + | if (!SD.begin(4)) { | |
- | + | continueText("failed"); | |
- | + | return; | |
- | + | } else { | |
- | + | continueText("succeeded");; | |
- | + | } | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
} | } | ||
- | void | + | void initLightSen() // initialize the light sensor |
{ | { | ||
- | + | lightsen.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS); | |
- | + | lightsen.enableAutoGain(true); | |
- | + | lightsen.begin(); | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
} | } | ||
- | void | + | void initWiFi() |
{ | { | ||
- | + | lcd.clear(COLOR_BLACK); | |
- | + | cursorY=1; | |
- | + | WiFi.disconnect(); | |
- | + | drawText("number of networks:"); | |
- | + | uint8_t nnet=WiFi.scanNetworks(); | |
- | + | continueText(String(nnet)); | |
- | + | for(int i=0;i<nnet;i++) | |
- | + | drawText(WiFi.SSID(i)); | |
- | + | drawText(); | |
- | + | drawText("connecting to YOURWIFI.."); | |
- | + | for(int i=0;WL_CONNECTED!=WiFi.begin("YOURWIFI","yourpassword")&&i<3;i++) | |
- | + | { | |
- | + | WiFi.scanNetworks(); | |
- | + | drawText(String("connection failed ")+String(2-i)+String(" left..")); | |
- | + | } | |
- | + | if(WiFi.status()==WL_CONNECTED) | |
- | + | { | |
- | + | continueText(" succeeded"); | |
- | + | drawText("local IP address: "+String(WiFi.localIP()[0])+"."+String(WiFi.localIP()[1])+"."+String(WiFi.localIP()[2])+"."+String(WiFi.localIP()[3])); | |
+ | } | ||
+ | else | ||
+ | drawText("connection failed"); | ||
+ | logging=0; | ||
+ | drawText(); | ||
+ | drawText("continue to data display & logging .."); | ||
+ | waitForTap(); | ||
+ | lcd.clear(COLOR_BLACK); | ||
+ | drawText("button: off",6); | ||
+ | continueText("logging: off",1,25); | ||
+ | String s="potentiometer: "+String((((float)analogRead(Poti))*0.0977517106549))+" "; | ||
+ | drawText(s,7); | ||
} | } | ||
- | void | + | void updateTP(){ |
- | { | + | tp.service(); |
- | + | drawText("x: "+String(tp.getX())+" y: "+String(tp.getY())+" ",2); | |
- | + | } | |
- | + | ||
- | + | void updateButtonAndPoti(){ | |
- | + | bool butv=(!digitalRead(Button)); | |
- | + | if(buttonValue!=butv) | |
- | + | { | |
- | + | if(wifiConnection==0) | |
- | + | { | |
- | + | initWiFi(); | |
+ | counter=1; | ||
+ | return; | ||
+ | } | ||
+ | if(butv) | ||
+ | { | ||
+ | logging=!logging; | ||
+ | if(logging) | ||
+ | { | ||
+ | continueText("logging: on ",1,25); | ||
+ | WiFiSend(); | ||
+ | counter=1; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | continueText("logging: off",1,25); | ||
+ | WiFiReceive(); | ||
+ | counter=1025; | ||
+ | } | ||
+ | } | ||
+ | if(!butv) | ||
+ | drawText("button: off",6); | ||
+ | else | ||
+ | drawText("button: on ",6); | ||
+ | buttonValue=!buttonValue; | ||
+ | } | ||
+ | uint16_t potv=analogRead(Poti); | ||
+ | if(potValue!=potv) | ||
+ | { | ||
+ | String s="potentiometer: "+String((((float)potv)*0.0977517106549))+" "; | ||
+ | drawText(s,7); | ||
+ | potValue=potv; | ||
+ | } | ||
+ | |||
} | } | ||
void updateRTC() // update the time from the clock | void updateRTC() // update the time from the clock | ||
{ | { | ||
- | + | DateTime tm=rtc.now(); | |
- | + | if(valueTime != tm.unixtime()) // Only refresh the values on the display if they changed (when the seconds value has changed since the last call) | |
- | + | { | |
- | + | char s[30]; | |
- | + | sprintf(s,"%02i:%02i:%02i %02i.%02i:%04i",tm.hour(),tm.minute(),tm.second(),tm.day(),tm.month(),tm.year()); | |
- | + | drawText(s,1); | |
- | + | } | |
- | + | valueTime = tm.unixtime(); | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
} | } | ||
- | void | + | void updateSenLight() // get current light values |
- | + | { | |
- | + | uint16_t lsbroadband,lsinfrared; // definition | |
- | + | float flsbroadband,flsinfrared; | |
- | + | lightsen.getLuminosity(&lsbroadband,&lsinfrared); // the full function is implemented in the library | |
- | + | flsbroadband=((float)lsbroadband*lightsen.getMultiplier()); | |
- | + | flsinfrared=((float)lsinfrared*lightsen.getMultiplier()); // getMultipier is a function I added. I believe the developers just missed something out in their lib | |
- | + | valueLight=(((float)valueCounter[2]*valueLight)+(float)flsbroadband)/(float)(valueCounter[2]+1.0); // Calculate the avaredged values | |
- | } | + | valueLightIR=(((float)valueCounter[2]*valueLightIR)+(float)flsinfrared)/(float)(valueCounter[2]+1.0); |
+ | valueCounter[2]++; | ||
+ | drawText(String("visible light: ")+String(flsbroadband,1)+" ",4); | ||
+ | drawText(String("infrared light: ")+String(flsinfrared,1)+" ",5); | ||
+ | float lratio=flsinfrared/flsbroadband; | ||
+ | continueText(String("ratio: ")+String(lratio,4),5,25); | ||
+ | uint8_t ledvw=-0.0000307574013*pow((double)log(flsbroadband)*25.5,3.0)+0.0117647055*pow((double)log(flsbroadband)*25.5,2.0); | ||
+ | analogWrite(ledW,ledvw); | ||
+ | uint8_t ledvr=-0.0000307574013*pow((lratio-0.2)*425.0,3.0)+0.0117647055*pow((lratio-0.2)*425.0,2.0); | ||
+ | analogWrite(ledR,ledvr); | ||
+ | uint8_t ledvg=-0.0000307574013*pow(255.0-((lratio-0.2)*425.0),3.0)+0.0117647055*pow(255.0-((lratio-0.2)*425.0),2.0); | ||
+ | analogWrite(ledG,ledvg); | ||
+ | bool alive; | ||
+ | if(flsinfrared<30.0&&flsbroadband>50) | ||
+ | alive=1; | ||
+ | else | ||
+ | alive=0; | ||
+ | mossstatus=alive; | ||
+ | } | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
} | } | ||
- | void | + | void updateSenWater() // get current water values |
{ | { | ||
- | + | float water = (0.0977517106549*(float)analogRead(Wat)); // The water sensor doesn't really work lineary. Here is my approximation for correction. | |
- | + | valueWater=((valueCounter[0]*valueWater)+water)/(valueCounter[0]+1); // avaredged value | |
- | + | valueCounter[0]++; | |
- | + | String s="water level: "+String(water)+"% "; | |
- | + | drawText(s,6); | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
} | } | ||
- | // | + | void updateSenTemp(){ // get current temperature data |
- | // | + | byte data[12]; // array the incoming values should be stored to |
- | // | + | byte addr[8] = {0x28,0x1D,0xF1,0xB0,0x04,0x00,0x00,0x6B}; // OneWire temperature sensor address |
- | // | + | |
- | // | + | tempsen.reset(); // build up a connection and request data |
+ | tempsen.select(addr); | ||
+ | tempsen.write(0x44,1); | ||
+ | tempsen.depower(); | ||
+ | tempsen.reset(); | ||
+ | tempsen.select(addr); | ||
+ | tempsen.write(0xBE); | ||
+ | for(byte z = 0; z < 9; z++) data[z] = tempsen.read(); // read out the return and store it byte per byte to the array | ||
+ | unsigned int raw = (data[1] << 8) | data[0]; | ||
+ | valueTemp=(float)((valueCounter[1]*valueTemp)+((float)raw / 16.0)-1.5)/(float)(valueCounter[1]+1); // Take the current temperature into account for the avaredged value | ||
+ | valueCounter[1]++; | ||
+ | String s="temperature: "+String(((float)raw / 16.0)-1.5)+" "; | ||
+ | drawText(s,3); | ||
+ | } | ||
- | void | + | void updateWiFiConnection(){ |
+ | uint8_t wstat; | ||
+ | if(!client.connected()) | ||
+ | client.stop(); | ||
+ | if(WiFi.status()==WL_CONNECTED) | ||
+ | wstat=1; | ||
+ | else | ||
+ | wstat=0; | ||
+ | if(wstat!=wifiConnection) | ||
+ | { | ||
+ | logging=0; | ||
+ | continueText("logging: off",1,25); | ||
+ | wifiConnection=wstat; | ||
+ | if(wstat) | ||
+ | { | ||
+ | continueText("WiFi: con",2,25); | ||
+ | continueText(" ",3,25); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | drawText(" ",10); | ||
+ | drawText(" ",11); | ||
+ | drawText(" ",12); | ||
+ | drawText(" ",13); | ||
+ | drawText(" ",14); | ||
+ | continueText("WiFi: dis",2,25); | ||
+ | continueText("button: recn",3,25); | ||
+ | |||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void WiFiSend() | ||
{ | { | ||
- | + | if(!client.connected()) | |
- | + | client.stop(); | |
- | + | drawText(" ",10); | |
- | + | drawText(" ",11); | |
- | + | drawText(" ",12); | |
- | + | drawText(" ",13); | |
- | + | drawText(" ",14); | |
+ | drawText("client connecting.. ",10); | ||
+ | cursorX-=11; | ||
+ | if(!wifiConnection) | ||
+ | { | ||
+ | updateWiFiConnection(); | ||
+ | return; | ||
+ | } | ||
+ | if(client.connect("your.website.here",80)) | ||
+ | { | ||
+ | continueText("connected"); | ||
+ | drawText("sending data..",11); | ||
- | + | client.print("GET http://your.website.here/save.php?key=yourkey"); | |
- | + | client.print(String("&water=")+String(valueWater,3) + "&temp="+String(valueTemp,3) + "&light1="+String(valueLight,3) + "&light2="+String(valueLightIR,3) +"&time="+String(valueTime)); | |
+ | client.println(/*" HTTP/1.1"*/); | ||
+ | client.println("Host: your.website.here"); | ||
+ | client.println("User-Agent: arduino-ethernet"); | ||
+ | client.println("Connection: close"); | ||
+ | client.println(); | ||
- | + | continueText("done"); | |
- | + | for(int i=0;i<3;i++) | |
- | + | valueCounter[i]=0; // Reset all counters and values for the avaredging process | |
- | + | valueWater=0.0; | |
- | + | valueTemp=0.0; | |
- | + | valueLight=0.0; | |
- | + | valueLightIR=0.0; | |
- | + | firstreceive=1; | |
+ | } | ||
+ | else | ||
+ | { | ||
+ | client.stop(); | ||
+ | continueText("failed"); | ||
+ | firstreceive=0; | ||
+ | return; | ||
+ | } | ||
} | } | ||
+ | void WiFiReceive() | ||
+ | { | ||
+ | int i=0; | ||
+ | if(firstreceive) | ||
+ | { | ||
+ | drawText(" ",10); | ||
+ | drawText(" ",11); | ||
+ | drawText(" ",12); | ||
+ | drawText(" ",13); | ||
+ | drawText(" ",14); | ||
+ | drawText("listening..",10); | ||
+ | firstreceive=0; | ||
+ | } | ||
+ | String response = ""; | ||
+ | while(client.connected() && i++<200) | ||
+ | { | ||
+ | if(client.available()) | ||
+ | { | ||
+ | while(client.available()) | ||
+ | { | ||
+ | response.concat((char)client.read()); | ||
+ | } | ||
+ | i=200; | ||
+ | client.flush(); | ||
+ | } | ||
+ | else | ||
+ | delay(1); | ||
+ | } | ||
+ | if(i==200) | ||
+ | Serial.println(); | ||
+ | Serial.print(response); | ||
+ | drawText(String(response),10); | ||
+ | } | ||
- | + | void setup() | |
- | + | { | |
- | + | initDisplay(); | |
- | + | Serial.begin(9600); | |
- | + | Serial.println("serial ready"); | |
+ | drawText("WiFi initialized"); | ||
+ | drawText("serial ready"); | ||
+ | drawText("init SD card reader.. "); | ||
+ | initSD(); | ||
+ | drawText("init some pins"); | ||
+ | analogReadResolution(10); | ||
+ | pinMode(Poti,INPUT); | ||
+ | pinMode(Button,INPUT); | ||
+ | pinMode(Temp,INPUT); | ||
+ | pinMode(Wat,INPUT); | ||
+ | pinMode(ledW,OUTPUT); | ||
+ | pinMode(ledR,OUTPUT); | ||
+ | pinMode(ledG,OUTPUT); | ||
+ | digitalWrite(Poti,HIGH); | ||
+ | digitalWrite(Button,HIGH); | ||
+ | analogWrite(ledW,255); | ||
+ | analogWrite(ledR,255); | ||
+ | analogWrite(ledG,255); | ||
+ | drawText("init touchpad"); | ||
+ | tp.init(); | ||
+ | tp.setOrientation(180); | ||
+ | drawText("init real time clock"); | ||
+ | rtc.begin(); | ||
+ | drawText("init light sensor"); | ||
+ | initLightSen(); | ||
+ | drawText("done"); | ||
+ | drawText(); | ||
+ | drawText("Tap for WiFi search and connection\n.."); | ||
+ | drawText("Press button to proceed without WiFi.."); | ||
+ | if(waitForTap()==0) | ||
+ | { | ||
+ | initWiFi(); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | lcd.clear(COLOR_BLACK); | ||
+ | drawText("button: off",6); | ||
+ | continueText("logging: off",1,25); | ||
+ | String s="potentiometer: "+String((((float)analogRead(Poti))*0.0977517106549))+" "; | ||
+ | drawText(s,7); | ||
+ | wifiConnection=0; | ||
+ | continueText("WiFi: dis",2,25); | ||
+ | continueText("button: recn",3,25); | ||
+ | } | ||
+ | } | ||
void loop() | void loop() | ||
{ | { | ||
- | + | if(counter%8==1) updateButtonAndPoti(); | |
- | + | if(counter%8==5) updateTP(); | |
- | + | if(counter%64==19) updateRTC(); | |
- | + | if(counter%64==37) updateSenWater(); | |
- | + | if(counter%128==11) updateSenLight(); | |
- | + | if(counter%128==73) updateSenTemp(); | |
- | + | if(counter%256==7) updateWiFiConnection(); | |
- | + | if(counter%4096==0&&logging) WiFiSend(); | |
- | + | if(counter%512==320&&logging) WiFiReceive(); | |
- | + | counter++; | |
- | + | delay(1); | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
} | } | ||
</nowiki> | </nowiki> | ||
Line 626: | Line 805: | ||
====Libraries==== | ====Libraries==== | ||
- | Since it | + | Since it is not possible uploading files of the type file'''.h''' or file'''.cpp''', we zipped our libraries, named the suffix '''.zip.txt''' and uploaded '''[[Media:TUM13_arduino_libraries.zip.txt|THEM]]''' to the wiki. To unzip the libraries simply remove the '''.txt'''. We're very sorry but it was simply to much code to locate it as text on our pages. |
Unzip the archive into your ./arduino/libraries folder. | Unzip the archive into your ./arduino/libraries folder. | ||
- | + | To store the sensor data the Arduino connects to a web server via WLAN. The sensor measurements are encoded as GET parameters and sent to the server in a HTTP request, then [[Team:TU-Munich/TUM13_save.ph|save.php]] stores them in a MySQL database. The data can be viewed by visiting [[Team:TU-Munich/TUM13_index.ph|index.php]], which accesses the MySQL database and plots the sensor data in a graph. To view new data sets in real time [[Team:TU-Munich/TUM13_real.ph|real.php]] periodically requests new data from the server by using AJAX. An example of this setup can be viewed at http://igem.wzw.tum.de/arduino. | |
Please also visit our [https://github.com/VonAlphaBisZulu/IGEM_ARDUINO GitHub repo.] | Please also visit our [https://github.com/VonAlphaBisZulu/IGEM_ARDUINO GitHub repo.] |
Latest revision as of 01:21, 29 October 2013
Our Tutorials
During our iGEM summer we have acquired many skills which are useful for iGEMers and for every synthetic biologist. In order to spread this knowledge we created some tutorials. We hope that these tutorials enable future iGEM teams to present their project in a more colorful fashion.
Wiki Tips & Tricks
Below is a list of iGEM wiki related tips and tutorials for future teams.
Picture viewer
Maybe you have not noticed it yet, but if you clicked any of the pictures on our wiki, you were not redirected to the ugly wiki page of the file. Instead a nice picture viewer opened and after you closed it, you did not have to go back to the site you saw the picture on. To get the same effect on your wiki follow the steps listed below:
- Get the files!
We modified the original slimbox 2 viewer to work with the wiki and to not exceed the browser viewport, so it is recommended to use our versions, which can be found at Team:TU-Munich/TUM13_slimbox2.css and Team:TU-Munich/TUM13_slimbox2.js. - Embed the files in your wiki!
The two files mentioned above and [http://jquery.com/ jQuery] have to be embedded on all the pages that should use the picture viewer. - Include the autoload code block!
A bit of JavaScript code that attaches the viewer to the right pictures needs to be executed on all the pages that use it. This code attaches the picture viewer to all images on the page which are embedded with the[[File:xxx.png|thumb|caption]]
wiki code and it adds the corresponding caption to the viewer.
$(document).ready(function(){ $("div.thumbinner > a img").slimbox({/* Put custom options here */}, function(el) { url = el.src; if (url.indexOf('thumb') != -1) { url = url.substring(0, url.lastIndexOf('/')); url = url.replace('/thumb/', '/'); } description = $(el).parents("div.thumbinner").children("div.thumbcaption").text(); return [url, description]; }, function(el) { return (this == el); }); });
- Test it!
Below is an example picture, click on it to see what the picture viewer looks like.
Slideshow
To create a good looking slideshow just follow the instructions below:
- Get the files!
You can get the Stylesheet and Javascript for the slideshow either from [http://bxslider.com/ bxSlider] or from our wiki: Team:TU-Munich/TUM13_bxslider.css and Team:TU-Munich/TUM13_bxslider.js.
- Embed the files in your wiki!
The two files mentioned above and [http://jquery.com/ jQuery] have to be embedded on all the pages that should use the slideshow.
- Include the initializing code block!
A bit of JavaScript code that activates the slideshow needs to be executed on all the pages that use it. This code changes all unordered lists of the class bxslider into slideshows.
$(document).ready(function(){ $('.bxslider').bxSlider({ responsive: false, auto: true, autoHover: true }); });
- Add the slideshow to the page!
To add a slideshow just put the pictures you want to include in an unordered list like shown below:
<html> <ul class="bxslider"> <li><img src="https://static.igem.org/mediawiki/2013/9/97/TUM13_slider_team1.jpg" /></li> <li><img src="https://static.igem.org/mediawiki/2013/3/30/TUM13_slider_team2.jpg" /></li> <li><img src="https://static.igem.org/mediawiki/2013/3/30/TUM13_slider_moos.jpg" /></li> <li><img src="https://static.igem.org/mediawiki/2013/6/66/TUM13_slider_kampen.jpg" /></li> </ul> </html>
- Test it!
Below is an example of the slideshow.
Generation of Rotating Protein Structures
Animated gifs of rotating protein structures have been used for some time in the iGEM competition. Here we present an easy to reproduce tutorial for iGEMers which are interested in similar images.
- If there is no PDB file available for your protein of interest, you can use a homology search to find the most homologous structure. A good homology search tool is [http://toolkit.tuebingen.mpg.de/hhpred HHpred].
- The entry for the best matching structure was used for the figure. If it is only a homologous structure please cite this together with the homology when presenting the resulting image.
- You can save the PDB file of the homologous structure on your computer.
- If you do not have [http://www.pymol.org/ PyMol] (freeware) installed on your computer download and install it.
- Start PyMol software and open the PDB file by clicking File -> Open.
- The following approach was adapted from a PyMol tutorial http://ihome.cuhk.edu.hk/~b102142/pymol/pymol_tutorial.html Wong.
- The following commands were entered into the command line:
PyMOL> orient
PyMOL> hide everything, all
PyMOL> show cartoon, all
PyMol> bg_color white
click> Settings>Rendering>Shadows>Occlusion
PyMOL> color purple, ss h; color yellow, ss s; color green, ss ""
PyMOL> show surface, all
PyMOL> set transparency, 0.75
PyMOL> set surface_quality, 1 (command will prolongue the process significantly, you may skip it)
PyMOL> set ray_trace_frames=1 (command will prolongue the process significantly, you may skip it)
PyMOL> mset 1 x180
PyMOL> util.mroll 1,180
PyMOL> mpng frame
- Afterwards the *.png files were automatically converted to *.tif files using [http://www.xnview.com/de/xnconvert/ XnConvert].
- The program [http://www.animake.de/gif-animation.htm Animake] was used to generate the annimated gifs.
- The Animake software was started
- A new working folder was generated (File -> New) and the *.tif files were imported (Edit -> Import_from_file)
- The background was set to white (Animation -> Settings)
- The range of colors was set to 256 (Edit -> Select_all and Edit -> Change_Color)
- The size of the file has to be reduced in order to be able to upload it on the iGEM wiki. This can be done by clicking Edit -> Change_size. We suggest a size of 320x240 px or even smaller if the resulting gif becomes to big.
- Finally the animated gif can be saved in the program format (.abp) and as gif (File -> Save_as)
- If you have problems to upload the file on the iGEM server you may try a reduced size (e.g. 300x225 px)
Setting up a basic Arduino measuring device
Introduction
Since the Arduino Due was released in autumn 2012, this is the first iGEM year this very powerful device can be used. We found it a useful supervising tool for short and long-term experiments. It can be used in as well as outside the lab. The improvements that were made from Uno to Due are considerable.
It is capable of handling many things at once, such as a WiFi shield, a display, a SD-Card and multiple sensors. At this point the Uno did not match up any longer.
To establish the usage of Arduino in iGEM even more we want to share our experiences and help you building up a basic device that can collect and view sensor data on its display and upload them to a server.
Part Description
Arduino Due
The Arduino Due is the most powerful Arduino board. Its underlying 32bit-processor is the Atmel SAM3X8E. Contrary to the other boards which run at 5V, a power supply of 3.3V is sufficient. It was released in October 2012.
Data:
84 Mhz CPU Clock 96 KBytes of SRAM. 512 KBytes of Flash memory. 54 Digital I/O Pins 12 Analog Input Pins 2 (DAC)Analog Outputs Pins
Arduino WiFi Shield
The Arduino WiFi Shield is an attachable shield that provides Wireless LAN 802.11b/g to the Arduino. It scans and connects to networks and opens TCP and UDP sockets for data transfer. It also supports WEP and WPA2 encryption. It was released in August 2012. The WiFi Shield is fully supported by the Arduino Due and Arduino supplies a suitable stock WiFi library. There is also an on-board SD-card socket to store received data. As the SD-card is accessible separately, it can also be used as a storage for any data generated by the Arduino. The SD-card socket is also supported by a stock library. The communication between Arduino Due and the WiFi Shield runs via an SPI/ICSP interface.
Pin usage:
Pin 4 SS for SD card (Slave Select) Pin 7 Handshake between Arduino and WiFi Shield Pin 10 SS for WiFi Pin 74 SPI MISO (Master in, Slave out) Pin 75 SPI MOSI (Master out, Slave in) Pin 76 SPI SCK (Serial clock) gnd 3.3V 5V
Watterott Mega MSD-Shield
The Mega MSD-Shield was designed by Watterott and consists of a couple of components. The components are one real time clock, one SD-card socket (we will not use), a small battery and a socket for a touch display. To get it ready to run, the shield must be assembled. The stackable headers and the clock's quartz must be soldered to the board and the battery must be inserted. Unluckily the Mega MSD-Shield and therefore also the MI0283QT-9 touch display don't come with a working library for the Arduino Due. The existing library only supports all boards up to the Arduino Uno. Therefore all libraries had to be rewritten. The touch display and the SD-card slot communicate with the Arduino Due via SPI/ICSP. The real time clock transmits its data via I²C.
Pin usage:
Pin 4 SS for SD card Pin 6 SS for the touch of the touch display Pin 8 reset LCD Pin 9 LCD LED Pin 20 RTC (real time clock) I²C SDA (Serial Data Line) Pin 21 RTC I²C SCL (Serial Clock) Pin 25 SS (7) for the LCD (Workarround of the double usage of pin 7 by the WIFI Shield) Pin 50 SPI MISO Pin 51 SPI MOSI Pin 52 SPI SCK gnd 3.3V
Display MI0283QT-9
The MI0283QT-9 is a multicolor touch display. It comes already attached to a board, where only the pin headers are left to be soldered. Once assembled it can easily be plugged into the Mega MSD-Shield. It has an on-board touch controller (TI ADS7846). The display size is 2.83"(43.2 x 57.6mm) with a resolution of 240x320. It supports 262k colors. The pin usage is already considered in the Mega MSD-Shield description.
Light Sensor TSL2561
The light sensor is a small, so called, breakout board. It is usually connected by wires instead of directly plugged into the Arduino's headers. The light sensor has two photo diodes on-board that measure visible and infrared light. Similar to the RTC, the TSL2561 is addressed via I²C. Once you get the I²C library working on your Arduino Due working it takes only little effort to integrate additional I²C devices. Just very few lines of the library have to be rewritten here. The photo diodes can be addressed separately or both at one. Their output is already converted to Lux.
Pin usage:
Pin 20 TSL2561 I²C SDA (Serial Data Line) Pin 21 TSL2561 I²C SCL (Serial Clock) gnd 3.3V
Temperature Sensor DS18B20
The temperature sensor is embedded into a water proof cable. It is addressed via a OneWire interface. The provided data are digital raw data, which need to be converted into degree Celsius. Information about the conversion are given by the manufacturer. Similar to the I²C (TwoWire) bus, you only have to get the OneWire interface working once. After that, you can easily set up more OneWire devices. Again, just very few lines of the library have to be rewritten.
Pin usage:
Pin 14 One-Wire DS18B20 (pin was randomly chosen) Pin gnd Pin 3.3V
Water Sensor
Setting up the water sensor is very easy. If and how much water the sensor registered can be measured via an analog pin.
pin usage:
Pin A5 Water sensor gnd 3.3V
Tools
- Breadboard
- Soldering bolt
- Solder
Assembly
Keep everything clear during your assembly. If you have different colored linking cables, always try to use the same color code (e.g. red cable for 3.3V etc.) otherwise troubleshooting can get nasty.
All steps you need to follow building up your own Arduino measuring device are explained below in the slide show and the image descriptions.
For more explaining photos visit our photo gallery. On the left you see the Arduino as it boots up, connects to a WiFi hotspot and collects data.
Code
We strongly recommend the usage of Microsoft Visual Studio with the "visual micro" plugin. Microsoft Intellisense helps you a lot, when you are unfamiliar with the manufacturer provided libraries (automatic code completion). In order to compile the code properly you need the latest beta version of [http://arduino.cc/en/Main/Software Arduino's software]. In the visual micro settings, choose the path to the Arduino IDE on your hard drive, also disable "Upload using programmer". In the settings of the Arduino IDE, select "use external software".
Now you are ready to start programming. Below we share our code, feel free to use, edit and play around with it! But wait first you need our libraries! They're exclusively fitted to the Arduino Due, mostly based on the existing manufacturer's libraries for the Arduino Uno.
Since Arduino released a new version of its IDE and software, and extended its support on the Arduino Due, we have rewritten our previews code. Both, the old and the new code can be found in our GitHub repo.
Assuming you followed our tutorial until here. Once you adapted the code to your WiFi and server settings and uploaded it to the Arduino it does the following:
- it starts up and the screen stays black, but turns its lights on
- if you have pressed the screen, the calibration process starts
- it searches for networks and displays the total number of found networks on its screen
- it displays some WiFi stations that were found
- it tries to connect to the WiFi station you have set
- if a connection was established it shows the Arduino's IP address and the SSID (name) of the WiFi it is connected to
- then it idles until you you press the screen
- after you pressed the screen it jumps to the "loop"-section of the code
- it continuously runs and displays:
- the current time
- the temperature
- the measured infrared and broadband light
- the coordinates of the point you pressed on the screen
- it builds up a connection to a server, calling a PHP script, passing on the collected data
#include "SPI.h" // SPI library (stock) #include "Wire.h" // TwoWire library (stock) sda-scl #include "RTClib.h" // Real time clock library (original library, slightly rewritten to fit the Due) #include "SPI.h" #include "MI0283QT9Due.h" // LCD library (quite much had to be rewritten). Pins were changed, usage of Software SPI... quite a mess but it works great #include "ADS7846Due.h" // Touch controller (same story as at the lcd library) #include "Adafruit_TSL2561.h" // light sensor library (had to be rewritten in some parts to fit the Due) functions were added to correct the lux-output that wasn't always correct with the stock library #include "OneWire.h" // OneWire (I don't know, but I guess it's the stock library) #include "avr/dtostrf.h" // optional library to workaround some compatibility problems with the Due #include "math.h" // standard C-maths library #include "SD.h" // SD reader (stock) #include "WiFi.h" // (stock) #include "time.h" // standard C-time library #include "math.h" #define ledW (11) #define ledR (12) #define ledG (13) #define Poti (A0) #define Button (A1) #define Temp (14) #define Wat (A5) #define shift8to32(a,b,c,d) (d << 24) | (c << 16) | (b << 8) | a #define shift8to16(a,b) (b << 8) | a MI0283QT9 lcd; ADS7846 tp; RTC_DS1307 rtc; OneWire tempsen(Temp); Adafruit_TSL2561 lightsen(TSL2561_ADDR_FLOAT,12345); File bitmap; WiFiClient client(0); float valueWater=0, valueTemp=0, valueLight=0, valueLightIR=0; // sensor values (avaredged) uint32_t valueTime=0,valueCounter[3]={0,0,0}; uint16_t counter=1,potValue=0; // vlauecounter 0:Water 1:Temp 2:Light/IR uint8_t cursorY=1,cursorX=0; bool buttonValue=0,logging=0,wifiConnection,mossstatus=0,firstreceive=1; int waitForTap(){ tp.service(); while(tp.getPressure()==0) // Idle until the touchscreen is pressed to continue { delay(20); tp.service(); if(digitalRead(Button)==0) return 1; } return 0; } void continueText(String drawtext, int cursY=cursorY-1, int cursX=cursorX,int maxlen=38){ maxlen=maxlen-cursX; lcd.drawText(15+cursX*8,cursY*15,drawtext,1,COLOR_WHITE,COLOR_BLACK); cursorX=drawtext.length()+1; } void drawText(String drawtext="", int cursY=cursorY,int maxlen=38){ continueText(drawtext,cursY,0); cursorY=cursY+1; } void OpenBMPFile(char *file, int16_t x, int16_t y) { uint8_t pad; uint8_t buf[54]; //read buf (min. size = sizeof(BMP_DIPHeader)) int16_t width, height, w, h; if(!SD.exists(file)) { Serial.println(String(file)+"not found"); return; } else bitmap = SD.open(file, FILE_READ); if(!bitmap.available()) { Serial.println("not reading image file"); return; } else Serial.println("reading image file"); //BMP Header for(int i=0;i<14;i++) { buf[i]=bitmap.read(); } if((buf[0] == 'B') && (buf[1] == 'M') && (buf[10] == 54)) { Serial.println("Bitmap recognized"); //BMP DIP-Header for(int i=14;i<54;i++) buf[i]=bitmap.read(); if( Serial.println(shift8to32(buf[14],buf[15],buf[16],buf[17]))&& // size Serial.println(shift8to16(buf[28],buf[29]))&& // bitspp Serial.println(shift8to32(buf[30],buf[31],buf[32],buf[33]))) // compress { Serial.println("DIP recognized"); //BMP data (1. pixel = bottom left) width = shift8to32(buf[18],buf[19],buf[20],buf[21]); // width height = shift8to32(buf[22],buf[23],buf[24],buf[25]); // height pad = width % 4; //padding (line is multiply of 4) Serial.println("printing"); if((x+width) <= lcd.getWidth() && (y+height) <= lcd.getHeight()) { lcd.setArea(x, y, x+width-1, y+height-1); for(h=(y+height-1); h >= y; h--) //for every line { uint8_t pix[320][3]; bitmap.read(pix,width*3); for(w=0; w < width; w++) //for every pixel in line { lcd.drawPixel(x+w, h, RGB(pix[w][2],pix[w][1],pix[w][0])); } if(pad) { bitmap.read(pix, pad); } } } else { lcd.drawTextPGM(x, y, PSTR("Pic out of screen!"), 1, RGB(0,0,0), RGB(255,255,255)); } } } bitmap.close(); } void initDisplay() { lcd.init(); lcd.setOrientation(180); lcd.led(100); lcd.clear(COLOR_BLACK); } void initSD(){ if (!SD.begin(4)) { continueText("failed"); return; } else { continueText("succeeded");; } } void initLightSen() // initialize the light sensor { lightsen.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS); lightsen.enableAutoGain(true); lightsen.begin(); } void initWiFi() { lcd.clear(COLOR_BLACK); cursorY=1; WiFi.disconnect(); drawText("number of networks:"); uint8_t nnet=WiFi.scanNetworks(); continueText(String(nnet)); for(int i=0;i<nnet;i++) drawText(WiFi.SSID(i)); drawText(); drawText("connecting to YOURWIFI.."); for(int i=0;WL_CONNECTED!=WiFi.begin("YOURWIFI","yourpassword")&&i<3;i++) { WiFi.scanNetworks(); drawText(String("connection failed ")+String(2-i)+String(" left..")); } if(WiFi.status()==WL_CONNECTED) { continueText(" succeeded"); drawText("local IP address: "+String(WiFi.localIP()[0])+"."+String(WiFi.localIP()[1])+"."+String(WiFi.localIP()[2])+"."+String(WiFi.localIP()[3])); } else drawText("connection failed"); logging=0; drawText(); drawText("continue to data display & logging .."); waitForTap(); lcd.clear(COLOR_BLACK); drawText("button: off",6); continueText("logging: off",1,25); String s="potentiometer: "+String((((float)analogRead(Poti))*0.0977517106549))+" "; drawText(s,7); } void updateTP(){ tp.service(); drawText("x: "+String(tp.getX())+" y: "+String(tp.getY())+" ",2); } void updateButtonAndPoti(){ bool butv=(!digitalRead(Button)); if(buttonValue!=butv) { if(wifiConnection==0) { initWiFi(); counter=1; return; } if(butv) { logging=!logging; if(logging) { continueText("logging: on ",1,25); WiFiSend(); counter=1; } else { continueText("logging: off",1,25); WiFiReceive(); counter=1025; } } if(!butv) drawText("button: off",6); else drawText("button: on ",6); buttonValue=!buttonValue; } uint16_t potv=analogRead(Poti); if(potValue!=potv) { String s="potentiometer: "+String((((float)potv)*0.0977517106549))+" "; drawText(s,7); potValue=potv; } } void updateRTC() // update the time from the clock { DateTime tm=rtc.now(); if(valueTime != tm.unixtime()) // Only refresh the values on the display if they changed (when the seconds value has changed since the last call) { char s[30]; sprintf(s,"%02i:%02i:%02i %02i.%02i:%04i",tm.hour(),tm.minute(),tm.second(),tm.day(),tm.month(),tm.year()); drawText(s,1); } valueTime = tm.unixtime(); } void updateSenLight() // get current light values { uint16_t lsbroadband,lsinfrared; // definition float flsbroadband,flsinfrared; lightsen.getLuminosity(&lsbroadband,&lsinfrared); // the full function is implemented in the library flsbroadband=((float)lsbroadband*lightsen.getMultiplier()); flsinfrared=((float)lsinfrared*lightsen.getMultiplier()); // getMultipier is a function I added. I believe the developers just missed something out in their lib valueLight=(((float)valueCounter[2]*valueLight)+(float)flsbroadband)/(float)(valueCounter[2]+1.0); // Calculate the avaredged values valueLightIR=(((float)valueCounter[2]*valueLightIR)+(float)flsinfrared)/(float)(valueCounter[2]+1.0); valueCounter[2]++; drawText(String("visible light: ")+String(flsbroadband,1)+" ",4); drawText(String("infrared light: ")+String(flsinfrared,1)+" ",5); float lratio=flsinfrared/flsbroadband; continueText(String("ratio: ")+String(lratio,4),5,25); uint8_t ledvw=-0.0000307574013*pow((double)log(flsbroadband)*25.5,3.0)+0.0117647055*pow((double)log(flsbroadband)*25.5,2.0); analogWrite(ledW,ledvw); uint8_t ledvr=-0.0000307574013*pow((lratio-0.2)*425.0,3.0)+0.0117647055*pow((lratio-0.2)*425.0,2.0); analogWrite(ledR,ledvr); uint8_t ledvg=-0.0000307574013*pow(255.0-((lratio-0.2)*425.0),3.0)+0.0117647055*pow(255.0-((lratio-0.2)*425.0),2.0); analogWrite(ledG,ledvg); bool alive; if(flsinfrared<30.0&&flsbroadband>50) alive=1; else alive=0; mossstatus=alive; } } void updateSenWater() // get current water values { float water = (0.0977517106549*(float)analogRead(Wat)); // The water sensor doesn't really work lineary. Here is my approximation for correction. valueWater=((valueCounter[0]*valueWater)+water)/(valueCounter[0]+1); // avaredged value valueCounter[0]++; String s="water level: "+String(water)+"% "; drawText(s,6); } void updateSenTemp(){ // get current temperature data byte data[12]; // array the incoming values should be stored to byte addr[8] = {0x28,0x1D,0xF1,0xB0,0x04,0x00,0x00,0x6B}; // OneWire temperature sensor address tempsen.reset(); // build up a connection and request data tempsen.select(addr); tempsen.write(0x44,1); tempsen.depower(); tempsen.reset(); tempsen.select(addr); tempsen.write(0xBE); for(byte z = 0; z < 9; z++) data[z] = tempsen.read(); // read out the return and store it byte per byte to the array unsigned int raw = (data[1] << 8) | data[0]; valueTemp=(float)((valueCounter[1]*valueTemp)+((float)raw / 16.0)-1.5)/(float)(valueCounter[1]+1); // Take the current temperature into account for the avaredged value valueCounter[1]++; String s="temperature: "+String(((float)raw / 16.0)-1.5)+" "; drawText(s,3); } void updateWiFiConnection(){ uint8_t wstat; if(!client.connected()) client.stop(); if(WiFi.status()==WL_CONNECTED) wstat=1; else wstat=0; if(wstat!=wifiConnection) { logging=0; continueText("logging: off",1,25); wifiConnection=wstat; if(wstat) { continueText("WiFi: con",2,25); continueText(" ",3,25); } else { drawText(" ",10); drawText(" ",11); drawText(" ",12); drawText(" ",13); drawText(" ",14); continueText("WiFi: dis",2,25); continueText("button: recn",3,25); } } } void WiFiSend() { if(!client.connected()) client.stop(); drawText(" ",10); drawText(" ",11); drawText(" ",12); drawText(" ",13); drawText(" ",14); drawText("client connecting.. ",10); cursorX-=11; if(!wifiConnection) { updateWiFiConnection(); return; } if(client.connect("your.website.here",80)) { continueText("connected"); drawText("sending data..",11); client.print("GET http://your.website.here/save.php?key=yourkey"); client.print(String("&water=")+String(valueWater,3) + "&temp="+String(valueTemp,3) + "&light1="+String(valueLight,3) + "&light2="+String(valueLightIR,3) +"&time="+String(valueTime)); client.println(/*" HTTP/1.1"*/); client.println("Host: your.website.here"); client.println("User-Agent: arduino-ethernet"); client.println("Connection: close"); client.println(); continueText("done"); for(int i=0;i<3;i++) valueCounter[i]=0; // Reset all counters and values for the avaredging process valueWater=0.0; valueTemp=0.0; valueLight=0.0; valueLightIR=0.0; firstreceive=1; } else { client.stop(); continueText("failed"); firstreceive=0; return; } } void WiFiReceive() { int i=0; if(firstreceive) { drawText(" ",10); drawText(" ",11); drawText(" ",12); drawText(" ",13); drawText(" ",14); drawText("listening..",10); firstreceive=0; } String response = ""; while(client.connected() && i++<200) { if(client.available()) { while(client.available()) { response.concat((char)client.read()); } i=200; client.flush(); } else delay(1); } if(i==200) Serial.println(); Serial.print(response); drawText(String(response),10); } void setup() { initDisplay(); Serial.begin(9600); Serial.println("serial ready"); drawText("WiFi initialized"); drawText("serial ready"); drawText("init SD card reader.. "); initSD(); drawText("init some pins"); analogReadResolution(10); pinMode(Poti,INPUT); pinMode(Button,INPUT); pinMode(Temp,INPUT); pinMode(Wat,INPUT); pinMode(ledW,OUTPUT); pinMode(ledR,OUTPUT); pinMode(ledG,OUTPUT); digitalWrite(Poti,HIGH); digitalWrite(Button,HIGH); analogWrite(ledW,255); analogWrite(ledR,255); analogWrite(ledG,255); drawText("init touchpad"); tp.init(); tp.setOrientation(180); drawText("init real time clock"); rtc.begin(); drawText("init light sensor"); initLightSen(); drawText("done"); drawText(); drawText("Tap for WiFi search and connection\n.."); drawText("Press button to proceed without WiFi.."); if(waitForTap()==0) { initWiFi(); } else { lcd.clear(COLOR_BLACK); drawText("button: off",6); continueText("logging: off",1,25); String s="potentiometer: "+String((((float)analogRead(Poti))*0.0977517106549))+" "; drawText(s,7); wifiConnection=0; continueText("WiFi: dis",2,25); continueText("button: recn",3,25); } } void loop() { if(counter%8==1) updateButtonAndPoti(); if(counter%8==5) updateTP(); if(counter%64==19) updateRTC(); if(counter%64==37) updateSenWater(); if(counter%128==11) updateSenLight(); if(counter%128==73) updateSenTemp(); if(counter%256==7) updateWiFiConnection(); if(counter%4096==0&&logging) WiFiSend(); if(counter%512==320&&logging) WiFiReceive(); counter++; delay(1); }
Libraries
Since it is not possible uploading files of the type file.h or file.cpp, we zipped our libraries, named the suffix .zip.txt and uploaded THEM to the wiki. To unzip the libraries simply remove the .txt. We're very sorry but it was simply to much code to locate it as text on our pages. Unzip the archive into your ./arduino/libraries folder.
To store the sensor data the Arduino connects to a web server via WLAN. The sensor measurements are encoded as GET parameters and sent to the server in a HTTP request, then save.php stores them in a MySQL database. The data can be viewed by visiting index.php, which accesses the MySQL database and plots the sensor data in a graph. To view new data sets in real time real.php periodically requests new data from the server by using AJAX. An example of this setup can be viewed at http://igem.wzw.tum.de/arduino.
Please also visit our GitHub repo.
Arduino photo gallery
- />
References
The 2D Graphic of the Arduino Due was taken from a open source software called "fritzing"
AutoAnnotator:
Follow us:
Address:
iGEM Team TU-Munich
Emil-Erlenmeyer-Forum 5
85354 Freising, Germany
Email: igem@wzw.tum.de
Phone: +49 8161 71-4351