tag:blogger.com,1999:blog-17604652486802967802024-03-19T01:09:57.226-07:00Anything GoesMichal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.comBlogger21125tag:blogger.com,1999:blog-1760465248680296780.post-66692803342925982332019-03-09T14:49:00.002-08:002019-03-10T19:42:53.010-07:00VSCode and MSP430 debuggingIn process of getting cozy with VSCode and playing with <a href="https://minkbot.blogspot.com/2019/03/ikea-ansluta-hacking-timer-and-key.html">MSP430</a> via LanchPad here is a simple recipe for tooling my work up.<br />
<br />
But first ...<br />
<br />
<h3>
Basic tooling</h3>
<br />
<ul>
<li>Build - uses <b>msp430-gcc</b>.</li>
<li>Debug - uses: <b>mspdebug</b> and <b>msp430-gdb</b></li>
</ul>
<br />
<br />
All msp430 tolls already prepackaged on multiple Linux distros (I use Mint which is Debian-based hence apt-get is your fried.)<br />
<br />
<h4>
Checking Connection to the Target</h4>
<div>
<br /></div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">mspdebug rf2500 "exit"</span><br />
<br />
<br />
If the output contains Device ID and Chip ID data you're good.<br />
<br />
If it can't connect try again with <i style="font-weight: bold;">sudo</i> in case the problem is with permissions. If it works with sudo, you add udev rules to allow non-root access - plenty of info in the tubes on this (I would advice a reboot after adding rules file).<br />
<br />
Sometimes, the hw debugger/drive gets stuck - a reconnect would fix it. Make sure it shows connected with '<b>lsusb|grep 430</b>'.<br />
<br />
<br />
<h4>
Flashing the image into the device</h4>
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">mspdebug rf2500 "prog ./bin/firmware.elf"</span><br />
<div>
<br />
<br /></div>
<h4>
Starting gdb Debug Server</h4>
<br />
The server is build into mspdebug it need to be running as gdb will use it to debug.<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">mspdebug rf2500 "gdb"</span><br />
<div>
<br /></div>
<div>
<h4>
Starting gdb Proper</h4>
</div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">msp320-gdb bin/firmware.elf -ex "target remote :2000"</span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
This tells the gdb to load debug info from the given elf file and execute commands to connect to the debug server. Normally, gdb uses this for remote debugin (as in on another PC) here the same is used for embedded systems.<br />
<br />
NOTE: each time you disconnect/quit gdb the debug server must be restarted.</div>
<div>
<br /></div>
<h4>
Convinience - Make File Targets</h4>
<div>
<br /></div>
<div>
In the Ikea Ansluta hacking project (<a href="https://github.com/michkrom/msp430-ansluta">on github here</a>) I have created make targets for continence:<br />
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">make target-flash</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">make target-startdebug</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">make target-debug</span></div>
<div>
<br /></div>
I think it's easier to remember these than particular incantation of commands given above.<br />
<div>
<br /></div>
<div>
The CLI workflow would be:</div>
<div>
<br /></div>
<div>
edit+build with <b><span style="font-family: "courier new" , "courier" , monospace;">make</span></b></div>
<div>
flash with <span style="font-family: "courier new" , "courier" , monospace;"><b>make target-flash</b></span></div>
<div>
debug with <b><span style="font-family: "courier new" , "courier" , monospace;">make target-debug</span></b></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><b><br /></b></span></div>
<div>
Note that target-flash makes sure the code build is up to date.<span style="font-family: "courier new" , "courier" , monospace;"><b><br /></b></span><br />
<div>
<h3>
VSCode tooling</h3>
</div>
<div>
<br /></div>
<div>
By adding tasks: build and flash I can Ctrl-Shift-B to build (as normal with VS) and I can also flash directly from the IDE be selecting "Flash" task. These are added to <a href="https://github.com/michkrom/msp430-ansluta/blob/master/.vscode/tasks.json">.vscode/tasks.json</a><span id="goog_1460379499"></span><a href="https://www.blogger.com/"></a><span id="goog_1460379500"></span> file manually. </div>
<div>
<br /></div>
<div>
Starting debbugger with just F5 is tooled via <a href="https://github.com/michkrom/msp430-ansluta/blob/master/.vscode/launch.json">.vscode/launch.json</a>. This tells VSCode to use "msp430-gdb" instead of default one and it tells it to connect to remote debug server.</div>
<div>
<br /></div>
<div>
However, I could not make the a <b>preLaunchTask</b> to start the msbdebug in the background. This task seem to either exit and kill the mspdebug or the mspdebug is unable to connect despite the rules working file in shell. So for now the debug server must be started manually before entering visual debugging in the IDE.</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDZfHPdY8T8loyV55nNy8ou8odi4OO8wst1lkPAab7n8ZPmWkxhI9brarqenANpWoV4YlITC_SLqJq9dem3yl0zL8tSXQTwz3JvMBRepNsF3jNsrXGckKHqb5Ff6GWMhjBfBqnVZQiluU/s1600/mspvsc.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="987" data-original-width="1385" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDZfHPdY8T8loyV55nNy8ou8odi4OO8wst1lkPAab7n8ZPmWkxhI9brarqenANpWoV4YlITC_SLqJq9dem3yl0zL8tSXQTwz3JvMBRepNsF3jNsrXGckKHqb5Ff6GWMhjBfBqnVZQiluU/s320/mspvsc.gif" width="320" /></a></div>
<br /></div>
<div>
<br /></div>
</div>
Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com1tag:blogger.com,1999:blog-1760465248680296780.post-49610752291107938912019-03-03T13:28:00.001-08:002019-03-03T13:28:51.506-08:00Ikea Ansluta Hacking - timer and key interruptsThat...was easy.<br />
<br />
1) setup interrupt for P1 on P_KEY (the switch) pin<br />
<br />
<div style="line-height: 19px;">
<div>
<span style="color: lime; font-family: Courier New, Courier, monospace; font-size: x-small;"> P2IFG = 0; // clear flags register<br /> P2IE = P_KEY; // enable<br /> P2IES = P_KEY; // edge</span><br /><br />2) setup timer A0 to use SMCLK/8 and count up, start it</div>
</div>
<br />
<div style="line-height: 19px;">
<div>
<span style="color: lime; font-family: Courier New, Courier, monospace; font-size: x-small;"> CCTL0 = CCIE; // CCR0 interrupt enabled<br /> TACTL = TASSEL_2 + ID_3 + MC_1; // TASSEL_2 --> SMCLK (~1MHz), MC_1--> up, ID_3 --> SMCLK/8<br /> CCR0 = 50000; // (SMCLK/8)/50000 = 2.5 Hz</span><br /><br />3) enter a low power mode with wake on interrupt</div>
</div>
<br />
<span style="color: lime; font-family: Courier New, Courier, monospace; font-size: x-small;"> _BIS_SR(CPUOFF + GIE);</span><br /><br /><br />4) in timer A0 - toggle the LED pin<br />
<br />
<span style="color: lime; font-family: Courier New, Courier, monospace; font-size: x-small;">#pragma vector = TIMERA0_VECTOR<br />__interrupt void Timer_A(void)<br />{<br /> P1OUT ^= P_LED; // toggle LED for now<br />}<br /><br /></span>5) in Port 1 interrupt - toggle the max count of timer A0 between 'slow' and 'fast' blinking.<br />
<span style="color: lime; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<div>
<span style="color: lime; font-family: Courier New, Courier, monospace; font-size: x-small;">#pragma vector = PORT2_VECTO<br />__interrupt void Port_2(void)<br />{<br /> // TODO - there is no debouncing of the switch<br /> if( P2IFG & P_KEY )<br /> {<br /> CCR0 = CCR0 > 10000 ? 10000 : 50000; // toggle between two blink speeds<br /> }<br /> P2IFG = 0; // clear all flags<br />}</span></div>
<div>
<span style="color: lime; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<br /></div>
Next: debounce the key, talk to CC2500.Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-57337624415873447732019-03-03T11:56:00.000-08:002019-03-03T13:39:46.695-08:00Ikea Ansluta Hacking - bang on the pipes (or...LED)After achieving <a href="http://minkbot.blogspot.com/2019/01/ikea-ansluta-hacking-system-via-tis.html">target control</a> and <a href="http://minkbot.blogspot.com/2019/01/ikea-ansluta-hacking-reverse.html">reverse engineering</a> the original firmware, the next step was to test development abilities: code, build, flash, debug.<br />
<h3>
</h3>
<h3>
Bang</h3>
The 'bang on the pipes' or 'flash LED'.<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>while(1)</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>{</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>LED(1);</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>DELAYLOOP(0xFFFF)</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>LED(0);</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>DELAYLOOP(0xFFFF)</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>}</span><br />
<div>
<br /></div>
Well, that's simple, eh? There some <a href="https://github.com/michkrom/msp430-ansluta/blob/master/src/main.c">more code in main.c</a> up front to setup the MPU. The Ansluta's specific definitions are all in <i><a href="https://github.com/michkrom/msp430-ansluta/blob/master/src/ansluta.h">ansluta.h</a>.</i><br />
<br />
The project is in github (later it may move beyond just flashing the LED).<br />
<a href="https://github.com/michkrom/msp430-ansluta">https://github.com/michkrom/msp430-ansluta</a><br />
<br />
<br />
The project builds from CLI on Linux (I now use Mint) but also contains VSCode workspace, intellisense and task definitions.<br />
<br />
<h3>
On VSCode</h3>
I have abandoned <a href="https://www.geany.org/">Geany</a> for <a href="https://code.visualstudio.com/">VSCode</a> for several reasons (it's shiny, integrates with git, it's used everywhere, it's good at at-hoc projects). Yes, VSCode is a bit "fatter", being an <a href="https://electronjs.org/">Electron</a> app, but it still works on my old-but-good 10yr laptop w/ 2GB of RAM with Mint x64.<br />
<br />
<h3>
Next Steps</h3>
Two "targets" (pun intended): get timer to flash led, get key press to work - all with interrupts. Then, talk to CC2500 radio.Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-22544413631191336302019-01-13T15:59:00.002-08:002019-01-13T23:01:47.839-08:00Ikea Ansluta Hacking - reverse engineering the firmwareSince acquiring target control via <a href="https://minkbot.blogspot.com/2019/01/ikea-ansluta-hacking-system-via-tis.html">Spy-Bi-Wire and LaunchPad</a> I am able to inspect and dump flash, disassemble and program back the flash to original stage<br />
<br />
The extracted files are in git here:<br />
<a href="https://github.com/michkrom/msp430-ansluta/tree/master/original">https://github.com/michkrom/msp430-ansluta/tree/master/original</a><br />
<br />
<h3>
Dumping Flash</h3>
In .hex intell format that is usable to programming it back:<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">mspdebug rf2500 "hexout 0xf800 2048 flash.hex"</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
In .raw binary format<br />
<div>
<br /></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">mspdebug rf2500 "save_raw 0xf800 2048 flash.raw"</span></div>
<div>
<br /></div>
<div>
<h3>
Reprogramming back to original</h3>
Use .hex Intel format<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">mspdebug rf2500 "prog flash.hex"</span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<div>
<h3>
Disassembling flash</h3>
</div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">mspdebug rf2500 "dis 0xf800 2048 flash.dis"</span></div>
</div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
Things learned from the disassembly:<br />
<br />
<ul>
<li>Operating mode is low power state LM3 and waking on interrupt from key press (connected to P2.7). However, LM1 is also entered after key press, perhaps to await for another key press before going LM3. Does this save energy?</li>
<li>Apparently, the randomization of remote's ID is done via...an ADC reads which ends up as middle 4 bytes of the message (each ADC read uses only lowest bit). That likely saves mfg time instead of individually programming each remote with ID - this is smart!</li>
<li>The SPI communication with CC2500 is bit-banged (not using build-in MSP's SPI engine). This is likely due to messed up hw design - the MOSI/MISO lines are switched from their default pins:</li>
</ul>
<br />
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">MSP430 Device</span></div>
<div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">----------------------------------------</span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> P1.0 LED</span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">RXD P1.1 unused?</span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">TXD P1.2 CC2500 CS</span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> P1.3 CC2500 GDO0</span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> P1.4 CC2500 GDO2</span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">SCLK P1.5 CC2500 SCLK</span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b><i>SOMI P1.6 CC2500 SI</i></b></span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b><i>SIMO P1.7 CC2500 SO</i></b></span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> P2.6 unused (N-FET's Gate in transformer)</span></div>
<div>
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> P2.7 Key (switch)</span></div>
</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-68128910252682220592019-01-12T12:01:00.006-08:002019-03-03T11:25:12.295-08:00Ikea Ansluta Hacking - target control via TI's lunchpadNotes of hacking Ikea <a href="https://www.ikea.com/ms/en_US/usearch/?query=Ansluta">Ansluta LED lighting</a>.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgyk5r056NOrT3nPim91PXTcS-6is5GWf2gqY_T7nwRtcpd25aA0Y3mQQZbeM8m5f-JiiO26veWcNIoth7uAZ8xLby2kVuifJzrCBULIYZFaOzF67qHT31Ev8wFd-o3ziiG5tlljZDri8/s1600/20181128_215135.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgyk5r056NOrT3nPim91PXTcS-6is5GWf2gqY_T7nwRtcpd25aA0Y3mQQZbeM8m5f-JiiO26veWcNIoth7uAZ8xLby2kVuifJzrCBULIYZFaOzF67qHT31Ev8wFd-o3ziiG5tlljZDri8/s200/20181128_215135.jpg" width="150" /></a><i>Notably, this is less important now as Ikea's own smart home gateway <a href="https://www.ikea.com/us/en/catalog/products/00337813/">TRÅDFRI</a> solves the problem of controlling Ansluta lights via home automation. Although, the system is very hack-able likely for other purposes.</i><br />
<i><br /></i>
<i><br /></i>
<i><br /></i>
<i><br /></i>
<i><br /></i>
<i><br /></i>
<i><br /></i>
<i><br /></i>
<i></i><br />
<h3>
Hardware</h3>
Both the remote and power supplies are based on TI's <a href="http://www.ti.com/product/MSP430G2231">MSP430 G2231</a> and <a href="http://www.ti.com/product/CC2500">CC2500 RF transciver</a>. The Ansluta's PCBs have programming/debugging headers ready for hacking.<br />
<br />
<div class="separator" style="clear: both; text-align: left;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnedAQcyUq7XucYlAk_ErWiDDmyR_8f2LBNk2Ul-KIS8hL8eHAO7255ZDgCv3PF2Rzra6PLzJg6E9ITUVW94LC4Zc_gGOMSSUYRGSiPgDs1sufLEd8EhI25I9QfrJJ6bSjVTaijYlb0yw/s1600/20190112_111423.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1002" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnedAQcyUq7XucYlAk_ErWiDDmyR_8f2LBNk2Ul-KIS8hL8eHAO7255ZDgCv3PF2Rzra6PLzJg6E9ITUVW94LC4Zc_gGOMSSUYRGSiPgDs1sufLEd8EhI25I9QfrJJ6bSjVTaijYlb0yw/s320/20190112_111423.jpg" width="200" /></a></div>
<br />
The 4 Pin Header by the Bat+ label (top) has the following pins: Vcc, T, R, Gnd (clearly labeled).<br />
<br />
I connected these to LP EXP430 Spy-Bi-Wire<br />
<span style="font-family: "courier new" , "courier" , monospace;">Vcc --> VCC (1)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">T --> TEST(17)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">R --> RST (18)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Gnd --> GND (20)</span><br />
<h4>
<span style="font-weight: normal;">The LunchPad Exp439G2 will power up the remote, no need for batteries. Just remove the actual MPU from the socket.</span></h4>
<h4>
<span style="font-weight: normal;">And...do not try this with transformer! this is dangerous as it's directly powered from power line.</span><br />
<span style="font-weight: normal;"><br /></span><span style="font-weight: normal;"><br /></span>
<br /><br />
<br />
</h4>
<div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4Q8fkz4hxiIxxaLaAHc1QqwqrqLeevGtKhzxnn1DKLemMnitxN2pbye7sMiJfqaFSg93Yul-SQNqoZlRw9W_0L8FC0cI8xyA2iA2b_RBokbUAjMS9QmXGx6ESiIKNYkIw93ALj0QICdE/s1600/ansluta_connections.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="376" data-original-width="401" height="299" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4Q8fkz4hxiIxxaLaAHc1QqwqrqLeevGtKhzxnn1DKLemMnitxN2pbye7sMiJfqaFSg93Yul-SQNqoZlRw9W_0L8FC0cI8xyA2iA2b_RBokbUAjMS9QmXGx6ESiIKNYkIw93ALj0QICdE/s320/ansluta_connections.PNG" width="320" /></a></div>
<h3>
Software</h3>
<h4>
Debugging the target</h4>
<div>
I am using lubuntu 18.04 and <a href="https://github.com/dlbeer/mspdebug">mspdebug</a> (0.25/compiled locally). and I am able to connect and break into the running code.<br />
<br />
Invoke (may need sudo):<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;">mspdebug rf2500</span><br />
<br />
Here is output (parts removed - there are complains about FET interface not working...)<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">Using Olimex identification procedure</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">Device ID: 0xf201</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Code start address: 0xf800</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Code size : 2048 byte = 2 kb</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RAM start address: 0x200</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RAM end address: 0x27f</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RAM size : 128 byte = 0 kb</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">Device: F20x2_G2x2x_G2x3x</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">Number of breakpoints: 2</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">fet: FET returned NAK</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">warning: device does not support power profiling</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">Chip ID data:</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ver_id: 01f2</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ver_sub_id: 0000</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> revision: 40</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> fab: 40</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> self: 0000</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> config: 02</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> fuses: 00</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">Device: F20x2_G2x2x_G2x3x</span><br />
<div>
<br />
run & break<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">(mspdebug) run</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">Running. Press Ctrl+C to interrupt...</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">^C</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ( PC: 0fc9e) ( R4: 077fd) ( R8: 0ff17) (R12: 00000) </span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ( SP: 0027a) ( R5: 0bf96) ( R9: 09ff6) (R13: 00006) </span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ( SR: 000da) ( R6: 0fffc) (R10: 0ff7f) (R14: 00006) </span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ( R3: 00000) ( R7: 0efcd) (R11: 00200) (R15: 00008) </span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">0xfc9e:</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 0fc9e: 30 41 RET </span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 0fca0: 0e 43 CLR R14</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 0fca2: 3e 90 2f 00 CMP #0x002f, R14</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 0fca6: 09 2c JC 0xfcba</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 0fca8: 4c 4e MOV.B R14, R12</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 0fcaa: 5d 4e 8a fd MOV.B 0xfd8a(R14), R13</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: x-small;">(mspdebug)</span><br />
<br /></div>
Next? Replace it with my own fw...when I have more time.<br />
<br /></div>
<h4>
Arduino with CC2250 </h4>
Here is <a href="https://github.com/michkrom/arduino/tree/master/cc2500">my version of Arduino+CC2500 </a>that is based on a great work done <a href="https://github.com/NDBCK/Ansluta-Remote-Controller">here</a>.<br />
<br />
It works!<br />
<br />
<h3>
References</h3>
<div>
<a href="https://docs.google.com/spreadsheets/d/16aYXkvqyzaALNKeKajb3j59D-8t1vjiyUnigd21tkbA/edit?usp=sharing" style="font-weight: 700;">spreasheet with MPC pin connections</a></div>
<div>
<br /></div>
<a href="https://github.com/NDBCK/Ansluta-Remote-Controller">https://github.com/NDBCK/Ansluta-Remote-Controller</a><br />
<br />
<a href="https://tildeslash.dk/Hacking%20IKEA%20Ansluta%20remote%20switch%20to%20work%20with%20Alexa.html">https://tildeslash.dk/Hacking%20IKEA%20Ansluta%20remote%20switch%20to%20work%20with%20Alexa.html</a><br />
<br />
<span style="background-color: white; color: #202124; font-family: "roboto" , "arial" , sans-serif; font-size: 16px; letter-spacing: 0.1px; white-space: pre-wrap;"><a href="http://www.ti.com/lit/an/slaa754/slaa754.pdf">TI Spy-by-wire</a></span><br />
<br />
<a href="http://karuppuswamy.com/wordpress/2010/10/22/debugging-msp-exp430g2-launchpad-with-mspdebug-tool-in-ubuntu-linux/">mspdebug+lunchpad</a><br />
<br />
<a href="http://www.simplyembedded.org/archives/debugging-with-gdb-mspdebug-and-ti-msp430-gcc/">mspdebug+gdb</a></div>
Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-43931379872545187772018-10-08T20:43:00.000-07:002018-10-08T20:44:59.238-07:00Picture Frame - gets PIR and saves energy<h2>
<br /></h2>
My <a href="http://minkbot.blogspot.com/2018/07/40-picture-frame-for-under-100.html">RPiPF</a> is doing good. So now the goal is to shut down the TV when nobody is watching.<br />
<br />
This was done. Many times. Even <a href="http://minkbot.blogspot.com/2010/">here</a>.<br />
<br />
A simple <a href="https://en.wikipedia.org/wiki/Passive_infrared_sensor">PIR (passive infrared)</a> connected to Rpi pin can be monitored and when no motion is detected for some time the TV gets turned off. This saves energy and potentially extends the TV life span.<br />
<br />
<h3>
The problem with (most) PIRs</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg21obES9e_BbQ_sb6C6c_lCg1MxdCheR231isAbZ-_zlGXcTfDbtLHXMIS8Zs8wRcnAUhEVJQiWPdtUIY2ZxBoT-Z7YRi6EZ6c5pDYoTojFOdvmvC5w85GI6IFZxA6N79EUKF5yMoB74U/s1600/pir.jpeg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="225" data-original-width="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg21obES9e_BbQ_sb6C6c_lCg1MxdCheR231isAbZ-_zlGXcTfDbtLHXMIS8Zs8wRcnAUhEVJQiWPdtUIY2ZxBoT-Z7YRi6EZ6c5pDYoTojFOdvmvC5w85GI6IFZxA6N79EUKF5yMoB74U/s1600/pir.jpeg" /></a></div>
The PIR devices are contain two main components: the actual sensor that converts light into electric signals and a very high-gain amplifier. And here the problem begins. The sensor gives a very weak signal that need to be amplified so it can be detected. The amplifier however will happily amplify anything on its input, including any interference. And RPI being a decently strong EM signal emitter (WiFi radio) when placed close to the sensor will cause unwanted tripping.<br />
<br />
I have tried the $5 sensors that worked great in the past, both with arduino and other laptops-picture-frames. These worked great as there was no interference source nearby.<br />
<br />
The aluminium foil shield did not work. Neither did attempt to decouple power supply with capacitors (apparently it is an inducted interference rather than a noise conducted via supply/ground lines).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdxlymZoYFoudmbtahTXr5yngD6eJX_Bh2nf2T8oR1Xxa1mh3G0RPF_VbI4B8OhMfBV7KjkWpdTojdz6cpAlPW9-DBXpN02UdG1_6pm3WFwVhwPA7GyzdqATGKs8Nk_uEbmiew0F4x4NI/s1600/minipir.jpeg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="224" data-original-width="224" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdxlymZoYFoudmbtahTXr5yngD6eJX_Bh2nf2T8oR1Xxa1mh3G0RPF_VbI4B8OhMfBV7KjkWpdTojdz6cpAlPW9-DBXpN02UdG1_6pm3WFwVhwPA7GyzdqATGKs8Nk_uEbmiew0F4x4NI/s200/minipir.jpeg" width="200" /></a></div>
However, I found this particular mini PIR sensor resilient to the interference. The cost being the sensitivity - it's detecting motion only in less then 3-4 meters away, while the other sensors were double this.<br />
<br />
<h3>
Bash the code</h3>
The complete code (bash script) is on github here:<br />
https://github.com/michkrom/pictureframe<br />
<br />
The main parts to make PIR work are:<br />
<br />
<ul>
<li>script to read the GPIO pin state: <a href="https://github.com/michkrom/pictureframe/blob/master/v3/bin/gpiord">gpiord <pinnum> </pinnum></a></li>
<li>scripts to turn TV <a href="https://github.com/michkrom/pictureframe/blob/master/v3/bin/tvon">on</a> and <a href="https://github.com/michkrom/pictureframe/blob/master/v3/bin/tvoff">off</a></li>
<li>main controller script monitoring the PIR and deciding when to turn the TV on or off: <a href="https://github.com/michkrom/pictureframe/blob/master/v3/bin/pf.sh">pf.sh</a></li>
</ul>
<br />
Bit and nuts of the script:<br />
<br />
Keep time: these two lines store current time int the form of number of seconds since 'epoh'. This is convenient when comparing them later.<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px; white-space: pre;">lastmotion=`date +%s`</span></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">...</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px; white-space: pre;">nowts=`date +%s`</span></span><br />
<br />
Here we read the pin #18, it's either 0 or 1.<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px; white-space: pre;">pinstate=`gpiord 18`</span></span><br />
<br />
And here we observe detected motion ($pinstate equal 1) and note when this happened.<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px; white-space: pre;"> if [ $pinstate -eq 1 ]; then</span></span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px; white-space: pre;"> lastmotion=$nowts</span></span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px; white-space: pre;"> fi </span></span><br />
<br />
Then compute how long it was since last time something moved<br />
<span class="pl-s" style="background-color: white; box-sizing: border-box;"><span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span class="pl-pds" style="box-sizing: border-box; font-size: 12px; white-space: pre;"></span></span></span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px; white-space: pre;"><br /></span></span>
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px; white-space: pre;"> let lastmotionage=$nowts-$lastmotion</span></span><br />
<br />
Then decide to show or not (by extending existing schedule condition)<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px; white-space: pre;"> if [ $lastmotionage -lt 600 ] && [ "$timeok" = true ]; then</span></span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace; font-size: 12px; white-space: pre;"> show=true</span><br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px; white-space: pre;"> fi</span></span><br />
<div>
<br /></div>
<div>
That's it.</div>
Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-36784123752482661502018-08-20T21:25:00.005-07:002019-03-03T11:24:27.326-08:00Picture Frame - a RPiPF on the schedule<h2>
</h2>
The previous builds were smaller but smarter. They actually turned off when nobody was around to see. The <a href="http://minkbot.blogspot.com/2018/07/40-picture-frame-for-under-100.html">RPiPF (RapsberyPi Picture Frame) </a>is not there yet.<br />
<br />
A small step forward: turn off when nobody's around to watch and turn on when there may be - on the schedule. Turn on at 7am, turn off 11pm.<br />
<br />
<h2>
To control the TV from RPI - CEC</h2>
<div>
<br />
<a href="https://en.wikipedia.org/wiki/Consumer_Electronics_Control">Consumer Electronics Control (CEC)</a> is a control channel over the HDMI cable.<br />
<br /></div>
Install cec-utils<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;">sudo apt-get install cec-utils</span><br />
<br />
Turn the TV off:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><span style="color: lime;">echo "standby 0" | cec-client -s -d 1</span> </span><br />
<br />
Turn the TV on<br />
<br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;">echo "on 0" | cec-client -s -d 1</span><br />
<span style="color: lime; font-family: "courier new" , "courier" , monospace;"><br /></span>
<br />
Don't mind the CLI plumbing - these command are like magic: '-s' means execute single command while '-d 1' limits the damage to you eyes by cutting down the logging spewed back at ya. Note that the echo just pipes the actual command to the cec-client - an interactive program by birth.<br />
<br />
<h2>
Flying on a Magic Script</h2>
<div>
The ph.sh script that was previously used to just start feh. Now it does the scheduling.</div>
<div>
The script loops and:</div>
<div>
<ul>
<li>checks the time</li>
<li>decides if the slide show should or should not be running</li>
<li>depending on that decision either </li>
<ul>
<li>kills feh and turns off the TV or </li>
<li>starts feh and turns on the TV</li>
</ul>
<li>sleeps for 1 minute and repeats</li>
</ul>
</div>
<div>
<br />
<pre><span style="color: lime;">logger "PF started"
PATH=$HOME/bin:$PATH
while true; do
now=`date +%H%M`
fehpid=`pidof feh`
if [ $now -gt 700 ] && [ $now -lt 2300 ]; then
if [ -z $fehpid ]; then
logger "PF now=$now fehpid=$fehpid ON"
tvon
gofeh &
fi
else
if [ ! -z $fehpid ]; then
logger "PF now=$now fehpid=$fehpid OFF"
skill feh
tvoff
fi
fi
sleep 1m
done</span>
</pre>
<h3 style="font-family: "times new roman"; white-space: normal;">
Taking it apart</h3>
<ul style="font-family: "times new roman"; white-space: normal;">
<li>The lines with 'logger ...' just put entries in /var/log/user.log so I know what was happening.</li>
<li>The line "PATH=" just adds /home/pi/bin (user's pi bin directory) to the path. Normally this should be done the .profile.</li>
<li>Then we loop forever...</li>
<li>The line 'now=... ' captures current time into the 'now' variable. The time is formatted as hhmm (in 24 hour format) for easier comparing later.</li>
<li>The 'fehpid=...' captures the process ID of feh, the slide show process. If it is not running, the fehpid is empty string.</li>
<li>Then in the first 'if' the script compares the $now to fit between 700 and 2300, military style.</li>
<li>And finally, the nested 'ifs' decide to turn on the show or to stop it. The '-z' checks for empty, while the '! -z' checks for not empty.</li>
<li><span style="font-family: "times new roman";">The small command scripts: </span><span style="font-family: "courier new" , "courier" , monospace;">tvon</span><span style="font-family: "times new roman";">, </span><span style="font-family: "courier new" , "courier" , monospace;">tvoff</span><span style="font-family: "times new roman";">, </span><span style="font-family: "courier new" , "courier" , monospace;">gofeh </span><span style="font-family: "times new roman";">got created in ~/bin (and </span><span style="font-family: "courier new" , "courier" , monospace;">chmod +x</span><span style="font-family: "times new roman";"> them so they can be executed).</span></li>
<li><span style="font-family: "times new roman";">The gofeh is run in the background (with '&') so the script can continue monitoring the time after starting the slide show.</span></li>
<span style="font-family: inherit;">
</span></ul>
<div style="white-space: normal;">
<h3 style="font-family: "times new roman";">
References</h3>
<div>
<a href="https://timleland.com/raspberry-pi-turn-tv-onoff-cec/">CEC on Pi</a></div>
</div>
<div>
</div>
</div>
Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-37312902212808003012018-07-30T21:20:00.001-07:002018-09-03T14:08:28.178-07:0040" Picture Frame For under $100<h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw52KZ7OCFZK73Fb1r6TeBE64bfl-fgT0nd1I2_swPfOVSsdeWhmYp8t_eNGZuuhRp1eShEZuKtNJ3ycwWFg0dRtm8hmj_sxraFs9ovI2nSBwC3zR4mRixLPlJvOm6WlHDRl4le47ffAs/s1600/20180730_201748.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw52KZ7OCFZK73Fb1r6TeBE64bfl-fgT0nd1I2_swPfOVSsdeWhmYp8t_eNGZuuhRp1eShEZuKtNJ3ycwWFg0dRtm8hmj_sxraFs9ovI2nSBwC3zR4mRixLPlJvOm6WlHDRl4le47ffAs/s320/20180730_201748.jpg" width="320" /></a></h2>
<h3>
<div style="font-size: medium; font-weight: 400;">
Yup, another version of my picture frame obsession (YAPF). I have turned several laptops into picture frames in the past. The Mark I, a <a href="http://minkbot.blogspot.com/2010/12/yapf-yet-another-pricture-frame.html">ca'95 HP laptop is still running strong</a>, 8 years non stop. The Mark II ca'99 HP laptops were not that strong. These died after few years...something changed in HP's quality about the new millenum...<br />
<br />
So here we go again! This time I am spending real $$$ on it!</div>
<div style="font-size: medium; font-weight: 400;">
<br /></div>
</h3>
<h3>
The ingredients:</h3>
<ol>
<li> A used HDTV from craigslist.org. Best, a TV with LED back-light and 1080p resolution (a 720p works too but the picture quality is not that great unless they are small.). I got a 4yr old Emerson LC401EM3F.for $75</li>
<li><a href="https://www.adafruit.com/product/2885">Rapsberry Pi Zero</a> $5 or better <a href="https://www.adafruit.com/product/3400">RPiZeroW</a> $10 (much more fun to access remotely)</li>
<li>miniSD card, greater than 4GB capacity $5</li>
<li>5V USB power supply (a charger better than 500mA), USB cable (to power RPi) $10</li>
<li>High-Speed Mini-HDMI to HDMI Cable, such as this <a href="https://www.amazon.com/gp/product/B014I8UAPE/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1">(Amazon Basic)</a> $5</li>
</ol>
<div>
Total about $95.<br />
<br /></div>
<h3>
Quick steps to the finish</h3>
<div>
Here are the steps to achive glory in less than an hour...that is if you know what you're doing. (Some skills required.)</div>
<h4>
Create Bootable Raspian Lite system. </h4>
There are plenty tutorials online how to do it <a href="http://lmgtfy.com/?q=raspbian+lite+tutorial">here</a>.<br />
<ul>
<li>Download Raspian Lite (at the time of writing it's STRETCH). <a href="https://www.raspberrypi.org/downloads/raspbian/">Here</a>. </li>
<li>Image your microSD card (on linux I use dd)</li>
<li>Connect a keyboard (needs a microUSB to USB cable/adapter, OTG works) to USB port.</li>
<li>Connect monitor via you cable (you can use adapters but the connectors on RPIW are fragile and close together so cable work better).</li>
<li>Power it up by plugging the USB charger/power supply into PWR connector.</li>
<li>You should see RPI booting.</li>
<li>After booting, log in as pi, password raspberry</li>
</ul>
<h4>
</h4>
<h4>
Configure the system, via raspi-config utility.</h4>
<ul>
<li>change password (if you want)</li>
<li>set hostname (if you want)</li>
<li>configure wifi (so you can log into it with ssh - applies only to RPIZ or if you plug inWiFi adaptor)</li>
<li>enable ssh</li>
<li>configure locale: US UTF-8, timezone</li>
<li>configure keyboard: Generic 104 PC, US than at the end there is option to set Ctrl-Alt-Backspace to kill X</li>
<li>configure boot to console (not graphical)</li>
<li>set to resize file system to full CD</li>
<li>reboot, check that wifi is connected (ping something), also check you can ssh to the system (handy later)</li>
</ul>
<h4>
</h4>
<h4>
Add to the system, as Lite is a bit...lite.</h4>
<ul>
<li>first update all</li>
<ul>
<li><span style="color: lime; font-family: "courier new" , "courier" , monospace;">sudo apt-get update && sudo apt-get upgrade -y</span></li>
</ul>
<li>reboot </li>
<li>install graphical display (xorg) and other utils</li>
<ul>
<li><span style="color: lime; font-family: "courier new" , "courier" , monospace;">sudo apt-get install --no-install-recommends xserver-xorg xinit x11-xserver-utils lightdm feh</span></li>
<li>note: the lightdm allows auto login to X; feh is the slide show application.</li>
</ul>
</ul>
<h4>
</h4>
<h4>
Configure scripts so things start automatically on every boot.</h4>
<ul>
<li>create ~/.xinitrc (this is what startx runs: disable x screen blanking and make it execute pf.sh at the end)<br /><span style="color: lime; font-family: "courier new" , "courier" , monospace;">xset s off<br />xset -dpms<br />xset s noblank<br />/home/pi/bin/pf.sh</span></li>
<li>create ~/bin/pf.sh to start feh in desired mode - full screen, randomized slide show 60s, no mouse etc and make it look for pictures in ... Pictures directory)<br /><span style="color: lime; font-family: "courier new" , "courier" , monospace;">feh -xrzYZFD60 --no-pointer --auto-rotate ~/Pictures</span></li>
<li>in ~/.profile add the following at the end (this runs startx on login from tty1 so autologin will use it)<br /><span style="color: lime; font-family: "courier new" , "courier" , monospace;">if [[ -z $DISPLAY ]] && [[ $(tty) = /dev/tty1 ]]; then<br />startx<br />fi</span></li>
</ul>
<h4>
</h4>
<h4>
Enjoy the view</h4>
<div>
Put some pictures in Pictures directory (you can use the <span style="color: lime;"><span style="font-family: "courier new" , "courier" , monospace;">scp</span> </span>utility via network).</div>
<div>
Connect da TV.</div>
<div>
Reboot.</div>
<div>
You should see RPI booting and then switching into graphical X and after a moment displaying the pictures.<br />
<br />
<h4>
DONE?</h4>
</div>
<div>
<br />
Ahh...No....not completely. I still want the YAPF.M3 to turn off when nobody is watching and back on when somebody is here (via a PIR sensor). More on this later (hooking PIR sensor, using HDMI CEC TV control and wrapping it all in a script).<br />
<br />
Here is how to add schedule to the YAPF.M3<br />
<a href="http://minkbot.blogspot.com/2018/08/picture-frame-rpipf-on-schedule.html">http://minkbot.blogspot.com/2018/08/picture-frame-rpipf-on-schedule.html</a></div>
<div>
<br /></div>
<div>
Also, since it's already connected to wifi, perhaps it could suck in the pictures itself? The disadvantage is that I am still using Picassa and which do not modify my pictures (Picassa just remembers the operations) and the pictures would be the resolution unnecessary higher than 1080p (20MP anyone?).<br />
<br />
<h3>
Github Repository</h3>
All the files are in github. These can be copied to the home directory: ~/home/pi.<br />
<a href="https://github.com/michkrom/pictureframe">https://github.com/michkrom/pictureframe</a><br />
<br />
<br />
<br /></div>
Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-91171291581045978622018-07-28T21:01:00.003-07:002018-08-22T22:40:16.278-07:00Google Assistant Marine WeathermanOnce upon a time, I decided that checking the weather on the phone while driving is not conducive to safety. But then I learnt about Google Assistant AI thingy that is changing the world...sorry Alexa!<br />
And here is a story of trying to build a Google Assistant skill for accessing marine weather information.<br />
<h2>
WHY</h2>
Soo...what marine whether data am I interested in? Wind, tides, fog, swell....I am a kite-surfer and my day-to-day ability to kite depends on catching the windy days. I need to know! Since I am on north California coast I depend on <a href="http://www.noaa.gov/">NOAA</a> and <a href="https://www.weather.gov/">NWS</a>.<br />
<h2>
WHAT</h2>
So here are some web weather resources I want to access via a speach-based application:<br />
<br />
Coastal Forecasts<br />
<a href="http://tgftp.nws.noaa.gov/data/forecasts/marine/coastal/">http://tgftp.nws.noaa.gov/data/forecasts/marine/coastal/</a><br />
Tide Predictions<br />
<a href="https://tidesandcurrents.noaa.gov/tide_predictions.html">https://tidesandcurrents.noaa.gov/tide_predictions.html</a><br />
Noaa Buoys:<br />
<a href="https://www.ndbc.noaa.gov/mini_station_page.php?station=44017">https://www.ndbc.noaa.gov/mini_station_page.php?station=44017</a><br />
<br />
<h2>
HOW</h2>
<div>
Google Assistant AI. Well...really the AI?...That depends on your definition of 'I'. IMHO, it is not AI - it is a speech-to-text (a very good one, mind you) then a text pattern matching filter with ability to invoke external web servers when matched a pre-canned pattern. It can't think by itself (the 'I' in AI is rather weak).</div>
<div>
<br /></div>
<div>
<h2>
LINGO</h2>
<br />
Here is the lingo, which took me quite a time to decipher:<br />
<br /></div>
<h3>
Google Assistant</h3>
<div>
A user facing system that can accept user input and provide, by some magic means, relevant output. Google Assistant (GA) has a plethora of 'native skill' and ability to invoke 3rd party applications (via 'talk to XYX'). There is also notion of <b>Actions </b>on google..I think it's just a fancy name for an Google Asistant application?<br />
<br /></div>
<h3>
Google Assistant Application</h3>
<div>
(aka skill...aka Action?) It is what I have created. GA apps are invoked by 'talk to XYZ', in my case it is 'talk to marine weather'. I tried to be funny but GA app name must be 2 or more words so Neptune or Poseidon did not work.<br />
<br /></div>
<h3>
DialogFlow</h3>
<div>
Is a text pattern matching system - my application (my Google Action) is a set of text patterns, aka <b><i>Intentions</i></b> (read: 'user intentions', 'user statements').</div>
<div>
(I suspect there is a close relation between defined patterns and a speech recognition as each time I update the pattern it says it's 'training...', likely speech recognition is much better if the correlator knows what to expect). DF also contain a system of describing parameters (ie the variables in intentions) via <b><i>Entities</i></b> and also linking intention to external web-based services (aka <b><i>Fulfilment</i></b>).<br />
<br /></div>
<h3>
DialogFlow Intentions</h3>
<div>
I have mentioned the <b>intentions</b>. These are the patterns that constitute one user desire (intention) and DF app may have many intentions. In intention, the same thing may be expressed many different ways:</div>
<div>
tides for bodega</div>
<div>
give me tides for bodega </div>
<div>
what are the tides for bodega</div>
<div>
bodega tides</div>
<div>
give me bodega tides</div>
<div>
etc..</div>
<div>
Intentions can have parameters here a 'location' would be a parameter. One can select a part of the example sentence and make it a parameter. So:</div>
<div>
tides for <i>'LOCATION'</i></div>
<div>
where location is a parameter. Which brings us to <b>entities</b>.<br />
<br /></div>
<div>
<h3>
DialogFlow Entity</h3>
</div>
<div>
Entity is a ... type (specification) of a parameter. You can use predefined entity (such as 'city' 'time' 'color' etc) or define your own or ... use @sys.any which is ...well anything.<br />
<br /></div>
<h3>
DialogFlow Fulfilment</h3>
<div>
Simple intention can have canned responses. You define them right in the dialog flow. But if you need to go to get some real time data, the fulfillment is where things get more interested. Fulfillment is essentially the GA/DF reaching to some other place in the WWW and getting a reply. So fulfillment is a www server accepting a https request returning a response. The request and response are GA-specific, JSON formatted collection of parameters. You can host this service yourself or you can use google services. The google services are called <b>Firebase</b>. Note, the Google Firebase is more generic than focused on GA/DF but there is a good support to make things easy.<br />
<br />
It's all pretty convoluted and overwhelming on the first date...</div>
Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-43305871871773474032018-07-09T21:49:00.000-07:002018-07-09T22:39:51.955-07:00It's been a whileYup, I got busy/lazy/having too much fun. This post is just to unplug the pipes, move the joints and warm up my fingers...<br />
<br />
Thing I have been toying with:<br />
<ul>
<li>Picture Frame Mark2</li>
<li>Ghost-busters backpack (Halloween Outfit)</li>
<li>Fulling around with MSP430</li>
<li>Fulling around with rPIs (3,zero,zerow)</li>
<li>Fulling around with MSP8266</li>
<li>Lego robotics help training</li>
<li>Odyssey of the Mind training</li>
<li>Hacking Ikea ANSLUTA remote</li>
<li>Building and flying quads and fix wings RC</li>
<li>Flying man-lifting kites in the waves.</li>
<li>Sailing sailing boats</li>
<li>Remodeling</li>
<li>Life</li>
</ul>
<div>
My current toyject (short for toy-project): Google Assistant app for Marine Weather.</div>
<div>
<br /></div>
<div>
Stay put, some of these will find it's way here.</div>
Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-81238882069903916972015-03-08T20:01:00.000-07:002015-03-10T13:59:32.869-07:00FS-T6 firmware upgrade<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYjx21CRNU6VsZe4QRVWWyl_kOhFv_Ux9XiclQ-ZERBlX8CVejEUMN0bOOrDBeywbQAw-Pcxz4zTaHoWxlaOEoE0qRboHBUR2Zok0r4Khv6FD39Xo0GykJeOUA0y1vfPYfq0exF4OBe1I/s1600/IMG_20150308_133052_rewind.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYjx21CRNU6VsZe4QRVWWyl_kOhFv_Ux9XiclQ-ZERBlX8CVejEUMN0bOOrDBeywbQAw-Pcxz4zTaHoWxlaOEoE0qRboHBUR2Zok0r4Khv6FD39Xo0GykJeOUA0y1vfPYfq0exF4OBe1I/s1600/IMG_20150308_133052_rewind.jpg" height="320" width="240" /></a>As we are working on <a href="https://github.com/art103/ar-t6">FS-T6 custom FW (called AR-T6)</a> we are trying to provide an easy path for early adaptors. Here is how to program the AR-T6 firmware into your Tx or revert to the original. Both without opening the case.<br />
<br />
<br />
What is needed:<br />
- <a href="https://code.google.com/p/stm32flash/">stm32flash utility</a> (can be build on linux and windows) or a <a href="http://www.st.com/web/en/catalog/tools/FM147/CL1794/SC961/SS1533/PF257525">STM loader demonstrator</a><br />
- compiled ar-t6.bin or <a href="http://openrcforums.com/forum/viewtopic.php?f=124&t=6329">original fs-t6.bin fw</a><br />
- serial port or <a href="https://www.adafruit.com/products/954">usb-to-serial adapter</a><br />
- some means to connect adapter's leads to the port on FS-T6<br />
- some knowledge of cmd line on linux <br />
<br />
<br />
<br />
<br />
Connections:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk1cUJGdYuNdZeitfvPIU3G3imzpkx7Q8zyHt-OLJ0i2hnF07uldtFB_WtQ6wDIvXNntSCnRm8aFAMPEsnk7wSE_OQ6_dHfnhw2u30RUj5_5l3wJDDVykYmUkBKe8EB-pewAyNsMQsxQ0/s1600/IMG_20150308_133213_rewind.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk1cUJGdYuNdZeitfvPIU3G3imzpkx7Q8zyHt-OLJ0i2hnF07uldtFB_WtQ6wDIvXNntSCnRm8aFAMPEsnk7wSE_OQ6_dHfnhw2u30RUj5_5l3wJDDVykYmUkBKe8EB-pewAyNsMQsxQ0/s1600/IMG_20150308_133213_rewind.jpg" height="320" width="240" /></a>BLACK - GND to the S-Video ring<br />
WHITE - PC Rx to T6's Tx<br />
GREEN - PC Tx to T6's Rx<br />
(see: <a href="http://minkbot.blogspot.com/2014/11/fs-t6-student-cable.html">student cable</a> for connections)<br />
<br />
Note that to get a good grounding I had to bend the pin of black ground wire and wedged it into the space.<br />
<span style="color: red;">Also note that the connection is potentially very flaky and may soft-brick your Tx if interrupted in the middle (recovery possible but only with an <a href="http://minkbot.blogspot.com/2014/10/fs-t6-and-swd-hack.html">SWD cable</a>). </span>A safer way would be to use a <a href="http://www.ebay.com/itm/231501106142">CT6B cable</a> or to make a custom cable from an S-Video one...as described <a href="http://minkbot.blogspot.com/2014/11/fs-t6-student-cable.html">here</a>)<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Linux<br />
<br />
check connection:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">~/stm32flash$ sudo ./stm32flash /dev/ttyUSB0 <br />stm32flash 0.4<br /><br />http://stm32flash.googlecode.com/<br /><br />Interface serial_posix: 57600 8E1<br />Version : 0x22<br />Option 1 : 0x00<br />Option 2 : 0x00<br />Device ID : 0x0420 (Medium-density VL)<br />- RAM : 8KiB (512b reserved by bootloader)<br />- Flash : 128KiB (sector size: 4x1024)<br />- Option RAM : 16b<br />- System RAM : 2KiB</span><br />
<br />
To program custom fw:<br />
<span style="font-family: "Courier New",Courier,monospace;">~/stm32flash$ sudo ./stm32flash -w ar-t6.bin -v /dev/ttyUSB0</span><br />
<span style="font-family: "Courier New",Courier,monospace;">stm32flash 0.4<br /><br />http://stm32flash.googlecode.com/<br /><br />Using Parser : Raw BINARY<br />Interface serial_posix: 57600 8E1<br />Version : 0x22<br />Option 1 : 0x00<br />Option 2 : 0x00<br />Device ID : 0x0420 (Medium-density VL)<br />- RAM : 8KiB (512b reserved by bootloader)<br />- Flash : 128KiB (sector size: 4x1024)<br />- Option RAM : 16b<br />- System RAM : 2KiB<br />Write to memory<br />Erasing memory<br />Wrote and verified address 0x0800f178 (100.00%) Done.</span><br />
<br />
<br />
To program custom fw:<br />
<span style="font-family: "Courier New",Courier,monospace;"></span><span style="font-family: "Courier New",Courier,monospace;">~/stm32flash$ sudo ./stm32flash -w fs-t6.bin -v /dev/ttyUSB0</span><br />
...<br />
<br />
<br />
In Original FW you go to Menu, System, scrol down to "Firmware Upgrade".<br />
In AR-T6 go to Menu, System, Version page, Menu (pres&hold SELect roller).<br />
<br />
<br />
Thanks go to Martin, <a href="http://martinschroder.se/hacking-flysky-fs-t6-transmitter/">here is his writeup</a>.<br />
<br />
<br />Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com9tag:blogger.com,1999:blog-1760465248680296780.post-27883241701685978262014-11-23T22:18:00.003-08:002014-11-23T22:36:23.685-08:00FS-T6 student cable<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQyc2PmnA4vMNjMMD_2r2GKP0mFs_XxO08laMbc2776dGMdpkqEXkbQ0ETOQdq3xw9JUmliQ54oqyESLbJ8Ot6lDMi73aDE-8j7VlvIoJLFKsL01dnftxsbaI2j_oFWJcU2fdYB264KKY/s1600/P1180102.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQyc2PmnA4vMNjMMD_2r2GKP0mFs_XxO08laMbc2776dGMdpkqEXkbQ0ETOQdq3xw9JUmliQ54oqyESLbJ8Ot6lDMi73aDE-8j7VlvIoJLFKsL01dnftxsbaI2j_oFWJcU2fdYB264KKY/s1600/P1180102.JPG" height="200" width="174" /></a>FS-T6 has a build in connector for another radio to be used as a trainer. However, the connector is rather unusual <a href="http://en.wikipedia.org/wiki/S-Video">S-VIDEO</a> one. There is a discussion about making a cable in the rcgroups:<br />
<a href="http://www.rcgroups.com/forums/showthread.php?t=1720333&page=4">http://www.rcgroups.com/forums/showthread.php?t=1720333&page=4</a><br />
<br />
<br />
The connector is on the back of the radio. It has 4 active pins and it uses connector shield for ground. Using standard s-video (see above wikipedia link) pins the signals on the radio are:<br />
1 - PPM TX<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3ShV64-YWDR0wlm77caLFpjYl2TwDpsu0PNdGY9OrH8JZNWne_7pYfnDbKANTltE-BEH9-6h1MAFphrODlPjJfro5wXXp5zNl3V1c7z79M5ulf_e750cW0pZimst071nEdXCulER3wBc/s1600/170px-MiniDIN-4_Connector_Pinout.svg.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3ShV64-YWDR0wlm77caLFpjYl2TwDpsu0PNdGY9OrH8JZNWne_7pYfnDbKANTltE-BEH9-6h1MAFphrODlPjJfro5wXXp5zNl3V1c7z79M5ulf_e750cW0pZimst071nEdXCulER3wBc/s1600/170px-MiniDIN-4_Connector_Pinout.svg.png" /></a>2 - PPM RX<br />
3 - SERIAL TX<br />
4 - SERIAL RX<br />
connector ring - GND<br />
<br />
The signals that needed to be connected between the two T6s are #1 and #2 crossed (ie TX of one radio goes to RX of another and vice-versa). I have decided to cross both PPM TX/RX and Serial TX/RX to avoid output shorts...(ie output driver another output). <i>Maybe one day we find a use for two radios communicating through a serial link? </i>This essentially creates a "null modem" cable.<br />
<br />
To make a cable you have 2 choices: 1) buy 2 plain connectors and solder the wires 2) rewire a standard s-video cable. Being a frugal guy I have opted for #2 (s-video cables are available for <$4 while single s-video connectors are more). However, standard S-VIDEO cables do not connect the grounds and connections are straight. Here, to connect two T6s you need to "cross the streams" and add the ground wire.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_zllJfFxmGHGkD7A5zn0p53q0ZqcyVs-5UTE37Ufo2qwzW77CQQLigQ5SGBiG2XpqpPZcOD1R0KqfaRfSyODg89sYwn2ygfInpsuS3xWGEpgwbWUWwwspTHdNmawwfbQ42g94ta5boD4/s1600/P1180103.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_zllJfFxmGHGkD7A5zn0p53q0ZqcyVs-5UTE37Ufo2qwzW77CQQLigQ5SGBiG2XpqpPZcOD1R0KqfaRfSyODg89sYwn2ygfInpsuS3xWGEpgwbWUWwwspTHdNmawwfbQ42g94ta5boD4/s1600/P1180103.JPG" height="240" width="320" /></a>Start with taking out the outside rubber. I cut the connectors first, Start cutting from the cable side to the connector to avoid cable damage (if you slip the knife). Then pull the rubber off.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhP8QuXCis_6xNingPurOYIBMGEWBj15E8MNnM3uBaoldNVSQllHksEIgIfjY8zND8f5y7YUPd9XinTyZ03xmRgbTZXfHBFyTqNm74-_PU3ZGAPS_raJ76Q0oQxY7hSmqq1M70evFEUqXY/s1600/P1180104.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/AVvXsEhP8QuXCis_6xNingPurOYIBMGEWBj15E8MNnM3uBaoldNVSQllHksEIgIfjY8zND8f5y7YUPd9XinTyZ03xmRgbTZXfHBFyTqNm74-_PU3ZGAPS_raJ76Q0oQxY7hSmqq1M70evFEUqXY/s1600/P1180104.JPG" height="136" width="200" /></a><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYkELsGaOZt5twZCpfqjTzvmhagIlaykoiON1_2Az13A1vNeR1LHY6CPQ5dl9ztnMI7SwGHtbt9W9SBrHfJ6nan4wZ2HZOo8hSPBgiYDyIAIj1yTGJUAI2LiErYOhdAfMtetHNOAO5-vA/s1600/P1180105.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYkELsGaOZt5twZCpfqjTzvmhagIlaykoiON1_2Az13A1vNeR1LHY6CPQ5dl9ztnMI7SwGHtbt9W9SBrHfJ6nan4wZ2HZOo8hSPBgiYDyIAIj1yTGJUAI2LiErYOhdAfMtetHNOAO5-vA/s1600/P1180105.JPG" height="169" width="200" /></a></div>
Next. Cut the cable in half In order to cross the streams. You may decide to do it in the middle (like I did). Or close to one of the connectors (if you want to wrap it with connector later).<br />
After cutting, unwrapping the shields, stripping the middle wire and re-soldering crossed over, I have wrapped them in electrical insulating tape. Note, the cross over is 1<-->2 and 3<-->4 which are on different cables (connect shield of one cable to center lead of another for each cable.).<!------><!------><!------><!------></--></--><br />
<br />
Than next I have added the ground wire. I have soldered it directly to the outside metal ring on both ends, then slipped the wire into a groove cut out in the connector plastic.<br />
<br />
<div class="" style="clear: both; text-align: left;">
The finished cable looks rahter nagly (nasty&ugly) but it works. However, the s-video connectors do not make solid mechanical plug. So if your plugs fall out as much as mine you'd want to lead the cable through the radio handles first and then plug it in. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVE1L1gLTyQV4e6ZEwk6xM3a8cfS_LZOe0TfstnxZWokOsBszfRFM_HwdTbtI_cESpyBPOeXYD602wjbKqRZmegcTraNBeRVAK8exdeBn1-QqgHitu7AIyVsrPiDAfVe7_hcV0KVUppnQ/s1600/P1180107.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVE1L1gLTyQV4e6ZEwk6xM3a8cfS_LZOe0TfstnxZWokOsBszfRFM_HwdTbtI_cESpyBPOeXYD602wjbKqRZmegcTraNBeRVAK8exdeBn1-QqgHitu7AIyVsrPiDAfVe7_hcV0KVUppnQ/s1600/P1180107.JPG" height="240" width="320" /></a></div>
<br />
My son and I flew together last week! It works!<br />
<br />Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com1tag:blogger.com,1999:blog-1760465248680296780.post-81580881817805569872014-10-28T22:05:00.003-07:002014-11-04T10:05:05.753-08:00FS-T6 and SWD hack<br />
<h3>
Preparing the FlySky-T6 RC TX for development with SWD. </h3>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3zzGOZZqgRhyphenhyphenBbO39xDrjbetWWXxOQnHWdlJa91mywg4j8cIReUgfsj20ceizuH5mtHBpgVyPC8cJp7vxrvum9XGdS1F51r87H7HBOYNDmZApmoa-3XREcweZdL5GrTwA__ZJcziTkb8/s1600/P1180047.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/AVvXsEj3zzGOZZqgRhyphenhyphenBbO39xDrjbetWWXxOQnHWdlJa91mywg4j8cIReUgfsj20ceizuH5mtHBpgVyPC8cJp7vxrvum9XGdS1F51r87H7HBOYNDmZApmoa-3XREcweZdL5GrTwA__ZJcziTkb8/s1600/P1180047.JPG" height="200" width="196" /></a><br />
<h3>
SWD = Single Wire Debug</h3>
Well, the SWD at a minimum requires 3 wires: clock, data and ground (great marketing though). In addition, it is very handy to add a reset line (nSRST_. This line would reset all the devices around the core CPU in the SoC chip in addition to restarting the CPU core. Otherwise, starting conditions would differ form run to run and I often see hangs. I have tried to use the 3 wires (aka ST-LINK V1, as featured on STM32FVLDISCOVERY with CPU similar to the T6's stm32f1xx chip). I did not like it. Hence later, I have hacked in the 6 pin connector.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX2nYkP-y9Wqt-Dw-5JbgUI42wGxAHxVu8g8ok3AbJGTGeuawwYPh0TnlCJIlAXUBkuiJzkukIZTOfO9oAPi50hTb3N5CiJqzZYID09pc2x5cH6MKWw9tHMpVtvAggm3EI_UKnX-Jh9vY/s1600/www.st.comst-web-uistaticactiveenresourcetechnicaldocumentuser_manualDM00092306.pdf+-+Google+Chrome+10282014+90748+PM.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX2nYkP-y9Wqt-Dw-5JbgUI42wGxAHxVu8g8ok3AbJGTGeuawwYPh0TnlCJIlAXUBkuiJzkukIZTOfO9oAPi50hTb3N5CiJqzZYID09pc2x5cH6MKWw9tHMpVtvAggm3EI_UKnX-Jh9vY/s1600/www.st.comst-web-uistaticactiveenresourcetechnicaldocumentuser_manualDM00092306.pdf+-+Google+Chrome+10282014+90748+PM.jpg" height="186" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">STM32F0Discovery</td></tr>
</tbody></table>
<h3>
Discovery</h3>
Discovery <a href="http://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/CD00267113.pdf">stm32f1discovery</a> is equipped with 4 pin SWD. All other discoveries AFAIK are ST-LINK V2 and come with 6 pin SWD. Remove the jumpers as shown on left to disconnect the on-board SWD control from the CPU (the one that also plugs into your PC's USB; discovery docs) then you can use the SWD connector to pulg it into T6.<br />
<br />
Notably, the V1 and V2 also differ in software. and in general the V2 is much more reliable according to openocd references.<br />
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7q9dvvYPnD3XOOIQWHdMN5twLJFkRxtjQk166b_4OtDQBZmzdLYAjt4mJoe7GRccCN6ZYr6s0QHa26s80sJhWzrTIM-QB53jyrlo-5E8CUILUL-iUrYdRlWEde4-0g69NQlcGzfs6B2o/s1600/Fullscreen+capture+10282014+85941+PM.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7q9dvvYPnD3XOOIQWHdMN5twLJFkRxtjQk166b_4OtDQBZmzdLYAjt4mJoe7GRccCN6ZYr6s0QHa26s80sJhWzrTIM-QB53jyrlo-5E8CUILUL-iUrYdRlWEde4-0g69NQlcGzfs6B2o/s1600/Fullscreen+capture+10282014+85941+PM.jpg" height="141" title="4-pin SWD as on VL discovery" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">4-pin SWD</td></tr>
</tbody></table>
<h3>
Schematics</h3>
Here are the schematics for 4,6 pin and full 20 pin SWD connector as seen on T6. <br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiODIdBXCRpZkDIavRfnASB2BiTT3kyWoE1L_Pe7KV2B5sCHCJQtP29pxUv5C-BtKNvChYIGLKiGatAqOU1ORD89nDrJqi6kvAgkjy6fCnRFWAB9MZKrFOR_v4RZDrLOPpOtX8AcPd81jc/s1600/www2.artaylor.co.ukimagesar-t6fst6.pdf+-+Google+Chrome+10282014+90100+PM.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a><br />
Note that SWD lines are also used by JTAG. Through some signaling magic CPUs would cpu obey (switch into) SWD instead of JTAG.<br />
<br />
<br />
<br />
<br />
The 4 pin is identical to the first 4 pins on 6-pin connector - handy!.<br />
<br />
<br />
<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6occ8eZKsU-0VtmJRyAH51kIODktNKt6FqEthy6lt5h1Qk1cp_VqgbK-ddtdbuRRKrnDq6XGsszxZfgmuHOL2uKpuaVBVhoO8u7qrgcnCW7-W1a9080K2Nh5qfN274Rocpajm6SrIt5k/s1600/www.st.comst-web-uistaticactiveenresourcetechnicaldocumentuser_manualDM00092306.pdf+-+Google+Chrome+10282014+90955+PM.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6occ8eZKsU-0VtmJRyAH51kIODktNKt6FqEthy6lt5h1Qk1cp_VqgbK-ddtdbuRRKrnDq6XGsszxZfgmuHOL2uKpuaVBVhoO8u7qrgcnCW7-W1a9080K2Nh5qfN274Rocpajm6SrIt5k/s1600/www.st.comst-web-uistaticactiveenresourcetechnicaldocumentuser_manualDM00092306.pdf+-+Google+Chrome+10282014+90955+PM.jpg" height="169" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">6-pin SWD</td></tr>
</tbody></table>
The VDO pin (pin 1 of the connectors) is not used - it is disconnected on discovery boards. I tied it to +3V3 on T6's side.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<h3>
Connections to T6</h3>
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiODIdBXCRpZkDIavRfnASB2BiTT3kyWoE1L_Pe7KV2B5sCHCJQtP29pxUv5C-BtKNvChYIGLKiGatAqOU1ORD89nDrJqi6kvAgkjy6fCnRFWAB9MZKrFOR_v4RZDrLOPpOtX8AcPd81jc/s1600/www2.artaylor.co.ukimagesar-t6fst6.pdf+-+Google+Chrome+10282014+90100+PM.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiODIdBXCRpZkDIavRfnASB2BiTT3kyWoE1L_Pe7KV2B5sCHCJQtP29pxUv5C-BtKNvChYIGLKiGatAqOU1ORD89nDrJqi6kvAgkjy6fCnRFWAB9MZKrFOR_v4RZDrLOPpOtX8AcPd81jc/s1600/www2.artaylor.co.ukimagesar-t6fst6.pdf+-+Google+Chrome+10282014+90100+PM.jpg" height="181" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">T6 20-pin "full" debug connector</td></tr>
</tbody></table>
<br />
<br />
I have connected the following:<br />
<span style="font-family: Courier New, Courier, monospace;"> U2(T6) CN3 (DISCO)</span><br />
<span style="font-family: Courier New, Courier, monospace;">+3.3V P1---P1 VDD </span><br />
<span style="font-family: Courier New, Courier, monospace;">TCK P9---P2 TCK</span><br />
<span style="font-family: Courier New, Courier, monospace;">GND P20--P3 GND</span><br />
<span style="font-family: Courier New, Courier, monospace;">TMS P7---P4 TMS</span><br />
<span style="font-family: Courier New, Courier, monospace;">nSRST P15--P5 NRST</span><br />
<span style="font-family: Courier New, Courier, monospace;">GND P18--P6 SWO</span><br />
<br />
Also the SWO is not available on F1xx CPU (this is used normally for trace output). This schematics is from <a href="http://www2.artaylor.co.uk/images/ar-t6/fst6.pdf">ar-t6</a> .<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYcRwVVaEjZagAV3uVNn63A_QyhJn7ffL1-D0Nh3kwiOSB1ATPScIk23FI9xBKtxrzvyiofsSxoGBahKdeZuI3l2EQok8fSiBcZmWojgdbRYTprG9qx5d3ufLR0T6j-Hj4oteUYCkzaJE/s1600/P1180045.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/AVvXsEhYcRwVVaEjZagAV3uVNn63A_QyhJn7ffL1-D0Nh3kwiOSB1ATPScIk23FI9xBKtxrzvyiofsSxoGBahKdeZuI3l2EQok8fSiBcZmWojgdbRYTprG9qx5d3ufLR0T6j-Hj4oteUYCkzaJE/s1600/P1180045.JPG" height="240" width="320" /></a>Here is the final result. Pin #1 is marked with a sqare, left lower row.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAA8Rtu43fWOptsbXddDak6sZnvZaSy-ty-kjE0FvtfjwOM_KcfavWac4K6yAGpOmuY3446QjpvdcBkoC5N4e8cIJAa5x8TzNEyse_V0oqbYY-JU3BRiMxt8u2W0Q5iwcGGraU3T8E8Qk/s1600/P1180044.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/AVvXsEgAA8Rtu43fWOptsbXddDak6sZnvZaSy-ty-kjE0FvtfjwOM_KcfavWac4K6yAGpOmuY3446QjpvdcBkoC5N4e8cIJAa5x8TzNEyse_V0oqbYY-JU3BRiMxt8u2W0Q5iwcGGraU3T8E8Qk/s1600/P1180044.JPG" height="240" width="320" /></a>I have also cut out small opening for a standard 6-ping header (female) that I have crimped and than hot-glued to the case. So now I can close the T6 and have it ready for flying in no time. Additionally, I found a 12V PS with correct plug and can now power T6 on my desk w/o batteries - this is a bonus and not required.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
Let me know.</div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: start;"><i>...sorry for formatting - blogger is a pile of streaming google...and google really stinks recently...</i></span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br /></div>
<!-- Blogger automated replacement: "https://images-blogger-opensocial.googleusercontent.com/gadgets/proxy?url=http%3A%2F%2F2.bp.blogspot.com%2F-3K8bGW2GFVs%2FVFBpKMDMSmI%2FAAAAAAAAS4M%2FpmLc1FZKtJ0%2Fs1600%2Fwww2.artaylor.co.ukimagesar-t6fst6.pdf%252B-%252BGoogle%252BChrome%252B10282014%252B90100%252BPM.jpg&container=blogger&gadget=a&rewriteMime=image%2F*" with "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiODIdBXCRpZkDIavRfnASB2BiTT3kyWoE1L_Pe7KV2B5sCHCJQtP29pxUv5C-BtKNvChYIGLKiGatAqOU1ORD89nDrJqi6kvAgkjy6fCnRFWAB9MZKrFOR_v4RZDrLOPpOtX8AcPd81jc/s1600/www2.artaylor.co.ukimagesar-t6fst6.pdf+-+Google+Chrome+10282014+90100+PM.jpg" --><!-- Blogger automated replacement: "https://images-blogger-opensocial.googleusercontent.com/gadgets/proxy?url=http%3A%2F%2F1.bp.blogspot.com%2F-9__Bs1MQy9g%2FVFBpJmSBcGI%2FAAAAAAAAS4E%2F5_P15Gw_aLU%2Fs1600%2FFullscreen%252Bcapture%252B10282014%252B85941%252BPM.jpg&container=blogger&gadget=a&rewriteMime=image%2F*" with "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7q9dvvYPnD3XOOIQWHdMN5twLJFkRxtjQk166b_4OtDQBZmzdLYAjt4mJoe7GRccCN6ZYr6s0QHa26s80sJhWzrTIM-QB53jyrlo-5E8CUILUL-iUrYdRlWEde4-0g69NQlcGzfs6B2o/s1600/Fullscreen+capture+10282014+85941+PM.jpg" -->Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com2tag:blogger.com,1999:blog-1760465248680296780.post-58156215235816662232014-10-27T22:08:00.000-07:002014-11-15T17:54:31.768-08:00Embedded software with Eclipse, Arm, Stm32fxxx, OpenOCD to develop FlySky FS-T6 trasmitter firmwareThis is a very terse dump of my experience of setting up a development environment for developing software for STM32Fxxx series of ARM processors. These CPUs come in a VERY inexpensive "discovery" boards (e.g. STM32F0DISCOVERY, STM32F3DISCOVERY, STM32F4DISCOVERY) - very fun to toy with (usually $10-20 and no need for any "emulators", "jtags" programmers etc). So this is cheaper then the famous "arduino" and you get a 32bit processor with tons of peripherals. I actually used this to start developing firmware for FlySky-T6 RC transmetter following the fantastic work here.<br />
<br />
In order to develop embedded software one usually needs: text editor, build tools, programmer/debugger tools. Here there are in order:<br />
- Eclipse<br />
- gnu arb toolchain<br />
- openocd<br />
<br />
The Eclipse is an IDE (Integrated Development Environment) that integrates editor, project management, build, debug documentation in one common, portable, extendable GUI.<br />
<br />
The gnu arb tool chain provides compiler/linker/stdlibraries/debugger to produce executable code.<br />
<br />
The openocd provides access to hardware. It can communicate with hardware debugger agent and provide flash memory access and debugger server that then can interact with gdb (the gnu tools debugger). An ST-LINK/ST-UTIL (texane or STM versions) can be used instead as well.<br />
<br />
<h3>
Eclipse/GNU/OpenOCD setup</h3>
Eclipse:<br />
<a href="http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a><br />
<br />
this usually ends up a "java" development without CDT ("C/C++"). I have downloaded Eclipse "Luna" .<br />
Install CDT Plugin (skip this if you've donwloaded a CDT-Eclipse):<br />
<a href="http://www.eclipse.org/cdt/downloads.php">http://www.eclipse.org/cdt/downloads.php</a><br />
in the above find correct "p2 repository" link --> Copy to clipboard<br />
in eclipse: Windows->Install New Software->Paste Link<br />
install main CDT + GCC and HW debug<br />
Install GNU ARM Plugin<br />
install "p2 repository": <a href="http://gnuarmeclipse.sourceforge.net/updates">http://gnuarmeclipse.sourceforge.net/updates</a><br />
re <a href="http://sourceforge.net/projects/gnuarmeclipse/files/Eclipse/updates">http://sourceforge.net/projects/gnuarmeclipse/files/Eclipse/updates</a><br />
Install GCC ARM toolchain (from launchpad):<br />
https://launchpad.net/gcc-arm-embedded/+download<br />
setup for win32 or in debian/ubuntu apt-get install<br />
Creating first project<br />
select "C/C++" perspective - on the right upper, if not there "+" (add) it<br />
file->new C/C++ project select one for your CPU; see below<br />
<br />
<span style="color: red;">WARNING</span> - after days of somewhat working debugger I faced gradual dysfunction: 1) eclipse stopbbed being able to interract with openocd in "pipe" mode (ie when it launches oocd itself) - I have switched to running oocd manually. 2) later it decided to gray out (disable) all debug buttons even after successful start and hitting a breakpoint. This was described in this thread:<br />
<a href="https://www.eclipse.org/forums/index.php/t/791751/">https://www.eclipse.org/forums/index.php/t/791751/</a>. Solution was to uninstall "GDB Hardware Debug support" (the openocd pluging started to work!).<br />
<br />
<h3>
OpenOCD - Windows</h3>
Specific to the ar-t6 firmware:<br />
Notes:<br />
On windows you'd get 2 build errors - can't find "echo" and "make" - solution is to steal them from codesourcery as per <a href="http://gnuarmeclipse.livius.net/blog/build-tools-windows/:">http://gnuarmeclipse.livius.net/blog/build-tools-windows/:</a><br />
<a href="http://sourceforge.net/projects/gnuarmeclipse/files/Miscellaneous/Cross%20Build%20Tools.zip/download">http://sourceforge.net/projects/gnuarmeclipse/files/Miscellaneous/Cross%20Build%20Tools.zip/download</a><br />
but an alternative would be to install gnuwin32 and add them to the path.<br />
<br />
Based on similar w/ CodeSourcery:<br />
<a href="http://en.radzio.dxp.pl/stm32vldiscovery/programming,with,opensource,toolchain,codesourcery,eclipse.html">http://en.radzio.dxp.pl/stm32vldiscovery/programming,with,opensource,toolchain,codesourcery,eclipse.html</a><br />
h<a href="ttp://gnuarmeclipse.livius.net/blog/openocd-install/">ttp://gnuarmeclipse.livius.net/blog/openocd-install/</a><br />
http://www.freddiechopin.info/en/download/category/4-openocd<br />
usb drivers for ST-LINK:<br />
<a href="http://www.st.com/web/catalog/tools/FM147/SC1887/PF258167">http://www.st.com/web/catalog/tools/FM147/SC1887/PF258167</a><br />
alternatively (not adviced) http://zadig.akeo.ie Options->show all->ST-LINK UpdateDriver<br />
<br />
There may be a need to install libusb0 (can't tell if it got installed with zadig or came with ST-LINK installation). Just in case you may want to install it from here:<br />
<a href="http://sourceforge.net/projects/libusb-win32/files/latest/download">http://sourceforge.net/projects/libusb-win32/files/latest/download</a><br />
<br />
Then in eclipse: <a href="http://gnuarmeclipse.livius.net/blog/openocd-debugging/">http://gnuarmeclipse.livius.net/blog/openocd-debugging/</a> but it does not run openocd so had to manually run<br />
"openocd -f stm32f0discovery.cfg -s c:\home\openocd-0.8.0\scripts"<br />
<br />
The solution is to change to windows backslashes. Make sure the cmd params are correct as eclipse would not give you any hints as to why it failed to start it.<br />
<br />
<h3>
Other/T6 related</h3>
<br />
STM32F1xx standard peripheral library<br />
<a href="http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1734/PF257890">http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1734/PF257890</a><br />
but no need for it as it comes with ARM plugin...<br />
<br />
I see occasional communication problems between eclipse (gdb?) and openocd debug server. Killing the openocd process from Task Man restarts system to working condition.<br />
git clone the ar-t6 into your "workspace" directory. the proceed to open project. If you do not know eclipse you will go through world of pain as it is not intuitive. That's okey, it will pass...<br />
<br />
The original project builds fine with gnu tools (with some warnings about code sourcery paths) . It contains CMSIS library (arm and stm parts).<br />
<br />
One needs to setup openocd "Debug Configuration" as per<br />
<a href="http://gnuarmeclipse.livius.net/blog/openocd-debugging/">http://gnuarmeclipse.livius.net/blog/openocd-debugging/</a><br />
<br />
Also in addition I have setup a special stm32f1-fst6,cfg (saved into openocd/scripts/board) :<br />
<br />
# This is an FlySky T6 base on STM32F100R8<br />
source [find interface/stlink-v2.cfg]<br />
source [find target/stm32f1x_stlink.cfg]<br />
# use hardware reset, connect under reset<br />
reset_config srst_only srst_nogate<br />
<br />
That's what goes into "config options" in the "debug" tab of debug configuration :<br />
-f stm32f1-fst6.cfg<br />
Try this from CLI<br />
openocd -f stm32f1-fst6.cfg<br />
<br />
It should report the chip id and number of hw breakpoins etc. and then wait for GDB to connect.<br />
<br />
Also in the debug configuration that you've set up per "openocd eclipse setup" I had to change the "debug/gdb client setup/executable" to explicitly say "arm-none-eabi-gdb" as the at-t6 project does not seem to define standard "cross-" macros. The debug configuration got committed to github as "ar-t6 Debug.launch" but it's a "Windows" one.Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-16017220812581727062011-04-20T22:26:00.000-07:002011-04-20T22:26:34.546-07:00Kitesurfing: Leading Edge Blowup Kite Repair<div class="separator" style="clear: both; text-align: right;"><a href="http://4.bp.blogspot.com/-IEYiEnuJfoM/Ta-qEnNk5qI/AAAAAAAAH6U/3_PJz64KfF0/s1600/P1070815.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="240" src="http://4.bp.blogspot.com/-IEYiEnuJfoM/Ta-qEnNk5qI/AAAAAAAAH6U/3_PJz64KfF0/s320/P1070815.JPG" width="320" /></a></div><span class="Apple-style-span" style="font-size: large;"><i>(experimental, ie do not follow)</i></span><br />
<br />
My Flexifoil Ion3 9m blew up. To add insult to the injury it blew up on the beach, in my hands when I was inverting it to pack and go home. Darn! Looks terrible. I simply think it just got old and tried to quit on me. No such luck, buddy! The quitting I mean, not getting old.<br />
<br />
So here is my attempted, DIYig (DIY in garage) revival report. Some things worked, some were messed up. I am yet to try to fly it...<br />
<br />
<a href="http://3.bp.blogspot.com/-p9dAbzSVmCw/Ta-qFoAGxVI/AAAAAAAAH6Y/DnU442BAGP0/s1600/P1070817.JPG" imageanchor="1" style="clear: left; display: inline !important; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="http://3.bp.blogspot.com/-p9dAbzSVmCw/Ta-qFoAGxVI/AAAAAAAAH6Y/DnU442BAGP0/s200/P1070817.JPG" width="200" /></a><br />
The repair was a two step process: the bladder and the canopy. Since I am lazy by nature I decide not to pull out the bladder completely but just slide it out of the tip. This was possible since the damage was close to the tip.<br />
So here it is, the bladder with a fist-size hole. They say, cut it open and glue a patch from the inside. I say no need to fix a hole by creating another hole.<br />
<a href="http://1.bp.blogspot.com/-H17T9Ca1Ics/Ta-qJOSQ_dI/AAAAAAAAH6o/YEvNSfm7vLM/s1600/P1070823.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="http://1.bp.blogspot.com/-H17T9Ca1Ics/Ta-qJOSQ_dI/AAAAAAAAH6o/YEvNSfm7vLM/s200/P1070823.JPG" width="200" /></a><br />
<br />
<br />
I removed the air connection from only one strut and rolled the bladder so it does not get in the way.Then I used some sticks to stretch damage area.<br />
<br />
I used a bigger-then-palm patch out of an old bladder and put it into the bladder through existing opening (technical term to describe a hole). Just made the patch way oversize so when glued with AquaSeal, the glue would not have a chance to glue the bladder's walls together. Here the black marks the edges of the patch (it's inside the balder). The glue already applied through the hole (I have cut out the original damaged area from the blown-out material).<br />
<br />
<a href="http://4.bp.blogspot.com/-yv0UKgaQdc8/Ta-qOmIssNI/AAAAAAAAH64/JYNB7oPuIb4/s1600/P1070836.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="http://4.bp.blogspot.com/-yv0UKgaQdc8/Ta-qOmIssNI/AAAAAAAAH64/JYNB7oPuIb4/s200/P1070836.JPG" width="150" /></a><br />
I have also applied another patch from the outside. I have spread the glue to keep the edges of the outside patch glued to the bladder.<br />
<br />
<a href="http://3.bp.blogspot.com/-oFrKb8USfK4/Ta-qPdVA9tI/AAAAAAAAH68/GnwFFzsS9Sc/s1600/P1070837.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="http://3.bp.blogspot.com/-oFrKb8USfK4/Ta-qPdVA9tI/AAAAAAAAH68/GnwFFzsS9Sc/s200/P1070837.JPG" width="200" /></a>After 12 hours under load, the glue turned yellow. I have not used AquaSeal before so I have not idea if this is OK....It feels flexible and strong.<br />
<br />
This is how it looks like cured.<br />
<br />
Anyway, the only other problem was that there were small pockets of air left between the patches. But is this a problem really?<br />
<br />
This part was relatively easy. The stitching required patience and a lot of ...<br />
Here it is, the top seam opened to make more space for sewing. I had only a fairly thick dacron from my boating days. I have also used the double sided sewing tape 3/4" (the white strips already attached to the edges of the damage. I have decided to put a single band of dacron and sew it in.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-B9EeWanOHSE/Ta-qTcJA33I/AAAAAAAAH7I/M6fQvKs5fTQ/s1600/P1070840.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="http://1.bp.blogspot.com/-B9EeWanOHSE/Ta-qTcJA33I/AAAAAAAAH7I/M6fQvKs5fTQ/s200/P1070840.JPG" width="200" /></a></div><br />
In order to help with alignment I first applied a insignia cloth to the outside. This helps keeping the edges together and in good place.<br />
<br />
Then I placed the dacron into the double sticky tape. The insignia cloth was a second take idea. I found that the sewing tape is not sticky enough to hold the edges together.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-nAk3C7mg-Ng/Ta-qZTx7UhI/AAAAAAAAH7Y/NT3_kLGdpK4/s1600/P1070844.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="http://4.bp.blogspot.com/-nAk3C7mg-Ng/Ta-qZTx7UhI/AAAAAAAAH7Y/NT3_kLGdpK4/s200/P1070844.JPG" width="200" /></a><a href="http://4.bp.blogspot.com/-I2TRmiYRKFY/Ta-qUFbNA1I/AAAAAAAAH7M/esY2w-hZe2g/s1600/P1070841.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="91" src="http://4.bp.blogspot.com/-I2TRmiYRKFY/Ta-qUFbNA1I/AAAAAAAAH7M/esY2w-hZe2g/s320/P1070841.JPG" width="320" /></a></div><br />
Sewing the seeds of love..ahem...adjusting my flaky walking foot machine is always a challenge, esp when I have not used it for a few years. She's got rusty, so did I.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-lYN-OtBVUdc/Ta-qcaZ5SLI/AAAAAAAAH7g/P32u9LaqIOo/s1600/P1070847.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="http://4.bp.blogspot.com/-lYN-OtBVUdc/Ta-qcaZ5SLI/AAAAAAAAH7g/P32u9LaqIOo/s200/P1070847.JPG" width="200" /></a></div>Four rows of zig-zag from the edge to the edge. I had to rip it out only once when the sail cloth got sewn in. Only once I swear!<br />
Then I got a brilliant idea to strengthen the cloth and put a spinnaker repair tape around the edges. Esthetic's got lost in the process (the tape is white).<br />
But where did the bladder go? I dropped it rolled into the LE shoulder. Kept it nicely out of the way.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-1BMNxp8KZhU/Ta-qdhOqU8I/AAAAAAAAH7k/OVmeSMuifMk/s1600/P1070848.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="http://4.bp.blogspot.com/-1BMNxp8KZhU/Ta-qdhOqU8I/AAAAAAAAH7k/OVmeSMuifMk/s200/P1070848.JPG" width="200" /></a></div>Sew him up, doc! I had to get the bladder out. Stretch it and somehow pray I will not sew it in while closing the leading edge.<br />
<br />
Here, under (minor) pressure test....It worked!. Just royally miscalculated (read "screw up") one small detail. The edges got quite strong with extra spinnaker tape and with the dacron (see: it is nicely going all the way from edge to edge). But...unfortunately, the dacron I used way thicker then the original cloth and hence I could not fold it. Darn! This made the repair downright ugly...<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-rK5GtEbPqN8/Ta-qiLTgUsI/AAAAAAAAH7s/O0DVa5Hr674/s1600/P1070850.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="http://4.bp.blogspot.com/-rK5GtEbPqN8/Ta-qiLTgUsI/AAAAAAAAH7s/O0DVa5Hr674/s200/P1070850.JPG" width="200" /></a></div><a href="http://3.bp.blogspot.com/-2xUnLVgvTjM/Ta-qg6GG7AI/AAAAAAAAH7o/U06mun5W-4Q/s1600/P1070849.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="http://3.bp.blogspot.com/-2xUnLVgvTjM/Ta-qg6GG7AI/AAAAAAAAH7o/U06mun5W-4Q/s200/P1070849.JPG" width="200" /></a><br />
<div style="text-align: center;"><b>the good</b></div><br />
<br />
This is plausible result. Kite survived nightly pressure test. and looks fine on the outside.<br />
<br />
<br />
<br />
<a href="http://3.bp.blogspot.com/-FG9ZizrUfhs/Ta-qjEVyRQI/AAAAAAAAH7w/-cmYpmnQ740/s1600/P1070851.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="http://3.bp.blogspot.com/-FG9ZizrUfhs/Ta-qjEVyRQI/AAAAAAAAH7w/-cmYpmnQ740/s200/P1070851.JPG" width="200" /></a><a href="http://4.bp.blogspot.com/-FZUHMmck_TA/Ta-qlygwHvI/AAAAAAAAH70/A3fMNzdcLxA/s1600/P1070852.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="http://4.bp.blogspot.com/-FZUHMmck_TA/Ta-qlygwHvI/AAAAAAAAH70/A3fMNzdcLxA/s200/P1070852.JPG" width="200" /></a><br />
<div style="text-align: center;"><b>the bad and the ugly</b></div><br />
Note the LE deformation. I suspect it could be a result of original damage and/or my sewing. It looks like the circumference is smaller in this area. Perhaps, I should redo the top seam. One day. Perhaps.<br />
<br />
Oh, well. I only meant the repair as an experiment....I do not think I'd take it into waves anymore. But on flats or as a learning kite it is still OK.Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com2tag:blogger.com,1999:blog-1760465248680296780.post-73735567604258386882010-12-20T23:02:00.000-08:002010-12-21T08:59:44.864-08:00YAPF - Yet Another Pricture Frame<div class="separator" style="clear: both; text-align: center;"></div><div style="text-align: left;"><b>with "viewer presents awareness" and geeky frame.</b> </div><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvH4x5KWgPOO8LX5zhDp3JgZuprBfpcuC-6GNddBB-Zsh2DHymmMZP0usgYFC4Pc7LUBf0MoocMbjS2gvcz-qyAU1yMHM_DtvzlZliFh4Hx0tTvAy9AjpYK_5oD-W5BnWHkuVccjthSRE/s1600/P1060697.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvH4x5KWgPOO8LX5zhDp3JgZuprBfpcuC-6GNddBB-Zsh2DHymmMZP0usgYFC4Pc7LUBf0MoocMbjS2gvcz-qyAU1yMHM_DtvzlZliFh4Hx0tTvAy9AjpYK_5oD-W5BnWHkuVccjthSRE/s200/P1060697.JPG" width="200" /></a><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Yup, yet another digital picture frame made from an old laptop. Added value: "viewer awareness intelligence". Say what? Ohh, nothing big. Simply a </span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://en.wikipedia.org/wiki/Passive_infrared_sensor">PIR</a></span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> (passive infrared sensor) to detect motion and turn on/off the back-light lamp. This prevents the lamp from burning out too quickly. To make things more interesting, a frame made out from discarded industrial printed circuit board. Perfect for the geek's house, ain't it?</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Why ?</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<a href="http://ii.alatest.com/product/190x190/9/8/Hewlett-Packard-HP-OmniBook-800CT-P-100-MHz-RAM-16-MB-HDD-810-MB-CD-Ma-0.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://ii.alatest.com/product/190x190/9/8/Hewlett-Packard-HP-OmniBook-800CT-P-100-MHz-RAM-16-MB-HDD-810-MB-CD-Ma-0.jpg" /></a><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I have few of these long-obsolete, unwanted laptops in my garage and a desire to do something with them. They work...sort of. You can run Win95 on one, a Win3.1 on another and DOS on the oldest one. OK, some of them are too old. I have picked a ca.1997 Omnibook 800CT (Pentium MMX 166MHz/80MB RAM 800x600 10" TFT LCD). </span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Now what?</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Obviously this has been done for years. Short recipe here: </span><br />
<ol><li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Get a CF card (>=128MB) and a laptop IDE-to-CF adapter (eBay)</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Using your USB card reader and your Linux Desktop (you have one, right?) install GRUB into it and a</span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> (preferably small) Linux distro.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Install a picture viewer of choice and make it run at start.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Copy pictures to a subdirectory.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Remove the screen hinges and the skirts (front plates) from the laptop, then build a frame around it.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Plug the CF & adapter in your laptop, reboot.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Enjoy.</span></li>
</ol><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Add salt to taste.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><b>Here are hints</b></span><br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh_bQQ0pPxeOmDFJqxCpFiJs7TGOghCPOJ64XOazJ2LsA_31Uux-6WGIV0sZ2uPd3twGvakwVpm1ELsOr3dwIfM-4xsnYIQv9ETXi0VJqUrrG7_Z1DXG58BKDeUb8_kYF0ImCkEKz5SvY/s1600/P1060675.2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh_bQQ0pPxeOmDFJqxCpFiJs7TGOghCPOJ64XOazJ2LsA_31Uux-6WGIV0sZ2uPd3twGvakwVpm1ELsOr3dwIfM-4xsnYIQv9ETXi0VJqUrrG7_Z1DXG58BKDeUb8_kYF0ImCkEKz5SvY/s200/P1060675.2.JPG" width="183" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">CF card & adapter in IDE connector</td></tr>
</tbody></table><ul><li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Use GRUB pre-2 </span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">version </span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">(I used 1.98). Newer may not work with old machines. There is plenty of help <a href="http://www.google.com/search?aq=f&sourceid=chrome&ie=UTF-8&q=installing+grub">on-line</a>.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I used </span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://www.tinycorelinux.com/">TinyCore</a>, a 10MB distro. On Omnibook 8xx series the Xvesa does not work so I had to install Xfbdev.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">For picture viewer I used FEH, avaliable for TinyCore as add on package. The only downside of FEH is lack of transitions, but with weak CPU this may be actually be a benefit.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><span class="Apple-style-span" style="font-family: 'Times New Roman';"><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Add a script to start FEH after X started. </span></span></span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The script that starts FEH goes into /home/tc/X.d/show.sh. It contains:</span></li>
<ul><li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">feh -rzFD60 --hide-pointer /mnt/hda1/Pictures &</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">as you see the pictures are in /mnt/hda1/Pictures (ie in the directory /Pictures in the top of the drive</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">the rest of options tell feh to do randomized slide show changing picture every 60s</span></li>
</ul></ul><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><span class="Apple-style-span" style="font-size: large;"></span></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><span class="Apple-style-span" style="font-size: large;"></span></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-bottom: 0.5em; padding-bottom: 6px; padding-left: 6px; padding-right: 6px; padding-top: 6px; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgowfuRnBx6L3SAd44bkUUJjo6FYX5eVkxVKrZkFox1FRbNcyQbv7DEryokFJYVSDtPi1dlHA_TLhJk91dikNSGN8TAgaL_BO4PaQTelaiGt4_RU8LfSPvQwFDsT202wZEkFtKkrnYkDcU/s1600/P1060674.JPG" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgowfuRnBx6L3SAd44bkUUJjo6FYX5eVkxVKrZkFox1FRbNcyQbv7DEryokFJYVSDtPi1dlHA_TLhJk91dikNSGN8TAgaL_BO4PaQTelaiGt4_RU8LfSPvQwFDsT202wZEkFtKkrnYkDcU/s200/P1060674.JPG" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 13px; padding-top: 4px; text-align: center;">Frame w/o laptop</td></tr>
</tbody></table><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><b>Mechanical stuff</b></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><b></b></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><b></b></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The frame is make of two identical PCBs one with elements the other blank. I have taken them from a pile of garbage. By size they are big. Old PC motherboards may be of use here. A dremel and angle grinder with cutting blade are your friends. All is held together by 6 stand-offs. The laptop slides in and is screwed into the front PCB.</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span></div><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><span class="Apple-style-span" style="font-size: large;"></span></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">PIR sensor aka "viewer presents awareness"</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">This was the most fun. It really had few parts: </span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">reading the PIR sensor, </span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">controlling the backlight, implementing the script to bind them all. </span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><b>To Port or not to Port</b></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhESUj2bsxVLaaVnJkCdp0KQS1szzl-WU-QJVnMOq5mQGLaaOva6QDalDliU2_NuAeCRDpLCvSo_UVcaFqv_NM9TtzR1HbbMvd9KDonMWcVxFCmJX6L10RDtkgz7HrlH48db33qFpfg2SA/s1600/P1060672.JPG" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhESUj2bsxVLaaVnJkCdp0KQS1szzl-WU-QJVnMOq5mQGLaaOva6QDalDliU2_NuAeCRDpLCvSo_UVcaFqv_NM9TtzR1HbbMvd9KDonMWcVxFCmJX6L10RDtkgz7HrlH48db33qFpfg2SA/s200/P1060672.JPG" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Laptop with PIR and PP connected<br />
The CPU part is tackled under.</td></tr>
</tbody></table><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">When this laptop was designed (ca.'95) there were no USB ports. But Parallel and Serial were in full swing. Both ports are easy to interface with and both have some lines that can be directly controlled (Serial has modem control likes, while Parallel is pretty much fully controllable). However, for the ease of software implementation I have chosen Parallel as it can be accessed from shell scripts through /dev/port. The down side of Serial is a harder control from scripts and its +/- 12V levels. So parallel it is.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">However, my laptop (like many other) has and open-collector outputs that are internally pulled-up by 1kOhm resistors. Way too much for the </span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Parallax PIR sensor I was planning to use (it ends up about 4mA drain). so I had to add a transistor "amplifier". </span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://www.scary-terry.com/itw/pirsensor/pirsensor.htm">Here</a></span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> is a good spill about the sensor and how to <a href="http://www.scary-terry.com/itw/pirsensor/pir-relay.jpg">connect some load to its "Out" pin</a>. The transistor output (collector) got connected to pint #15 of the port (which leads to bit #4 in </span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">STAT register</span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">).</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><b>Let there be...darkness</b></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizyFZoX16ZzQbX9598ZGASDR7l6gk3z1ShgMxSrxlzIFJRCQHpDaelYta-jyqe2pTkSt1mOwBa83TcH09j1OVDhYBuLUHH5i3668av4_Dp9v433I7yRtPw1TKqBGQ1EcqIncUY8SO_Y3s/s1600/P1060673.JPG" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="122" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizyFZoX16ZzQbX9598ZGASDR7l6gk3z1ShgMxSrxlzIFJRCQHpDaelYta-jyqe2pTkSt1mOwBa83TcH09j1OVDhYBuLUHH5i3668av4_Dp9v433I7yRtPw1TKqBGQ1EcqIncUY8SO_Y3s/s320/P1060673.JPG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Modified inverter and PIR output amplifier. <br />
All powered from +5V available on the inverter.</td></tr>
</tbody></table><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">How to control backlight? There are more then a few ways. Normally, newer hardware would have ACPI which has backlight control. But my laptop has older APM which does not. So much for direct control. Another idea would be to decipher the keyboard and pretend a "PWR" button press, which turns the display off (but let the CPU to continue). This proved hard to interface as the keyboard is connected through the thin "foil" connectors. So, in desperation I looked at the <a href="http://en.wikipedia.org/wiki/CCFL_inverter">CCFL inverter</a> and, the proverbial "bulb" went on in my brain. The inverter is build around <a href="http://parts.digikey.com/1/parts/627212-ic-sw-reg-ccfl-contrast-16-soic-lt1184cs-pbf.html">LT1184CS</a> chip, which has a "shutdown" pin. Bingo! Well, not quite. A little probing showed that the pin is shorted to +5V by some buried trace. So I got out my 6-pack of whoop-ass and lifted the pin. Added pull up 6kOhm resistor (probably not necessary as PP has pull-ups but I did not want the darkness when not in control). Then connected it to pin #14 (bit #1 in CONTROL register). </span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><b>Scribbling the scripts</b></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><b><br />
</b></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I choose to implement the monitoring of the PIR in shell scrpt. There are 3 scripts: rdport, wrport and monitor. All placed in ~/.local/bin and invoked from .profile. Granted, I could simply hooked up the PIR to a timer such as NE555 and control the backlight directly. But writing script was more fun. As benefit, the scripts can log activity in my house (do not know why I'd need it though).</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Again, few obstacles to be solved:</span><br />
<ol><li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">how to read/write a port</span></li>
<ul><li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">access through '/dev/port'</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">must be root hence 'sudo'</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">use dd with seek/skip </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">sudo dd bs=1 count=1 of=/dev/port seek=$1</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"></span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">convert a string '123' to actual byte : </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">echo -n $2 | awk '{printf("%c",$0)}'</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"></span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">convert byte to a sting: </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">hexdump -e '/1 "%u"'</span></li>
</ul><li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">how to interpret and generate binary values</span></li>
<ul><li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">motion=`dc $pir 8 xor 8 and p`</span></li>
</ul></ol><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The script to read any ISA port 'rdport [addr]<addr>':</addr></span><br />
<span class="Apple-style-span" style="background-color: white; font-family: 'Courier New', Courier, monospace;">sudo dd bs=1 count=1 if=/dev/port skip=889 2>/dev/null | hexdump -e '/1 "%u"' </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The script to write any ISA port 'wrport [addr] [val]<addr><val>':</val></addr></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="background-color: white; font-family: 'Courier New', Courier, monospace;">echo -n $2 | awk '{printf("%c",$0)}' | sudo dd bs=1 count=1 of=/dev/port seek=$1 2>/dev/null</span><span class="Apple-style-span" style="background-color: white; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> </span></div><div><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif; font-size: x-small;">There is a small problem with this script as I cannot write 0. I think the busybox implementatino of awk's prints has problems printing 0 as this is a string terminator in C</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">. </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br />
</span></div><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">A script to monitor the PIR state and control the CCFL inverter "shutdown". This is the "brain". The addresses of PP CONTROL and STATUS registers are 889 and 890. The script only updates the 'shutdown' signal when its state actually changes.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The jest:</span><br />
<ul><li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">loop forever</span></li>
<ul><li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">check the sensor state</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">if motion detected update "last motion" time stamp</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">if "last motion" time stamp tool old (here 300 seconds) then turn off the backlight</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">otherwise turn on the backlight</span></li>
</ul></ul><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">#!/bin/sh</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"># monitor PIR sensor and control backlight</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"># handy function for time-stamping</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">now() { </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> echo -n `date +%s` </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"># initialize start conditions</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">maxElapsed=300 # 300 SECONDS = 5 MIN</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">off=1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">lastMotion=$(now)</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"># loop forever</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">while true; do</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> # read and check PIR (bit #3 of ParPort hence mask is 2^3=8)</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> pir=`rdport 889`</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> motion=`dc $pir 8 xor 8 and p`</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> if [ $motion -ne 0 ]; then</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> lastMotion=$(now)</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fi</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> # see if enough time elapsed since last registered motion</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> elapsed=$(expr $(now) - $lastMotion)</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> if [ $elapsed -gt $maxElapsed ]; then</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> requestOff=1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> else</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> requestOff=0</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fi</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> #echo $pir $motion $lastMotion $elapsed $expired $off</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> # if changes the state of backlight then apply it</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> if [ $requestOff -ne $off ]; then</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> off=$requestOff</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> if [ $off == 1 ]; then</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> echo -n 'OFF: ';date;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> wrport 890 2</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> else</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> echo -n 'ON : ';date;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> wrport 890 1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fi</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fi</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">done</span><br />
<div style="font-family: 'Trebuchet MS', sans-serif;"><br />
</div><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><b><span class="Apple-style-span" style="font-size: large;">Todo</span> </b></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><b><br />
</b></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I'd like to have Forward/Backward buttons.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Have it WiFied to my picture archive (g</span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">et a better laptop for this).</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Make it serve beer.</span></span></div><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Go on line and download some ...wait!</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif; font-size: large;"><b>THE END</b></span>Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-41371833760975791452010-10-11T23:40:00.000-07:002010-12-19T23:28:25.689-08:00Kitesurfing: Replacing a strut bladder with U-Stick orange bladders<span class="Apple-style-span" style="font-size: medium;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Here is a story of a bladder (replacement) on an inflatable kite.</span></span><br />
<span class="Apple-style-span" style="font-size: medium;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></span><br />
<div><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5527027085635005906" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDuxcesqh7eYUIUFGVwrf-a5tLOqb5OfL1Y6EkJHX5-76NjlZFeXjMOCXglWq8qmcZgyCqM_lbrAsOyIJ7efMNl4ra_jFBVtXogA-lFVkvMburIhGx7YvuWKuR_J1BrQh5po_lQLKsaqw/s200/P1060116.JPG" style="height: 200px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; width: 150px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Twice-Broken valve</span></td></tr>
</tbody></table><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: medium;"></span>Recently, I had a failure in my Flexifoil 9m Atom3 after I left it simmering in the sun for several hours (at Rio Vista, CA.) After having an "interesting" session with half-deflated kite I was faced with a repair. The heat caused delamination of the strut valve from the bladder. I have had local repair shop repair it. They glued the valve back but the repair looked terribly (with some part of bladder glued together, ripped apart and left hangin and bladder folds). I have reinstalled it anyway and tested it overnight. It held the air. I did not go out for several days (no, the kite was no longer on the sun).</span></div><div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Next time I have inflated it on the beach the kite quickly lost lots of air. I discovered that although the glue held, the valve become cracked and it had a serious leak. Apparently the repair damaged the valve base. The damage looked like it was heat induced. I bet it was overheated during the repair (the valve is usually completely unglued by "coocking" it). So much for "professional" repair.</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><div><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsyAg_s2z0DZq4aL6lSSt9zvk3RzKmSYfxapcF-Vc3bx1F5kS8I7Pfxb_lcKtzXa8XMaN2-nrGlH_NhcgQijd2ja8-BOpxgsI7rVYeu-nouDjOd_eHChvmq8Fcs3iMLgNu0dDzHxw-Uf8/s1600/P1060113.JPG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><img alt="" border="0" height="120" id="BLOGGER_PHOTO_ID_5527024759967994594" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsyAg_s2z0DZq4aL6lSSt9zvk3RzKmSYfxapcF-Vc3bx1F5kS8I7Pfxb_lcKtzXa8XMaN2-nrGlH_NhcgQijd2ja8-BOpxgsI7rVYeu-nouDjOd_eHChvmq8Fcs3iMLgNu0dDzHxw-Uf8/s320/P1060113.JPG" style="height: 75px; margin-top: 0px; width: 200px;" width="320" /></span></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Orange and original bladders.</span></td></tr>
</tbody></table><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">So, a full bladder replacement was in order: U-Stick orange bladder and valve. The <a href="http://shop.airtimekite.com/">Airtime</a> Kite people were awesome. They quickly advice me what I should use. The strut valves, both on main and strut bladder are called "option" as you can choose different stems. Flexifoil has a 11mm valves with straight stems. There is also a "replacement" option valve which does not have "options" as it comes only with straight stem. Also, Airtime has nice on-line bladder selection tools. My kite needed 50cm bladder. The valves fit the opening in the kite and did not need rings. Ordering and shipment was a snap, thanks Airtime!</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I followed instructions attached to the bladder and valve. However, there were few small surprises.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The 50cm bladder is visibly much bigger then the original Flexifoil one. Too big is OK as the kite will restrict the expansion, too small would be bad (too much stretch). The original bladder was also 50cm (just much smaller). </span><br />
<span class="Apple-style-span" style="color: black;"><span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; color: black;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="color: black;"><span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; color: black;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The material is more brittle sounding (it sounds more like a "shopping bag" while Flexifoil's is more like "sex-rubber", if you know what I mean.) Just observing the visual difference which has nothing to do with other physical properties like strength. I just said "oh well it must work fine."</span></span></span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">REALLY be careful when cutting the hole in the bladder for the valve. The bladder is completely air tight when shipped so pulling it apart is hard. Never thought that vacuum can be so hard :-)</span></div><div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsxPG6lR7YQdkEDACUmOvRc4_qjP5J0gWuqnT9c7LjROpxCljukdIgKYwzJsD8FjbSJz7k78i3kENalP8Wybn7ZxKDKnahfKR2T9pv8SPpv5X7n2FqYZh3GfX7QkxwC9_VdVCs50KRuCY/s320/P1060118.JPG" style="margin-left: auto; margin-right: auto;" width="320" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Bladder prepared for surgery</td></tr>
</tbody></table><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsxPG6lR7YQdkEDACUmOvRc4_qjP5J0gWuqnT9c7LjROpxCljukdIgKYwzJsD8FjbSJz7k78i3kENalP8Wybn7ZxKDKnahfKR2T9pv8SPpv5X7n2FqYZh3GfX7QkxwC9_VdVCs50KRuCY/s1600/P1060118.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"></span></a></div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">When sticking the valve there were more surprises.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The bottom of the valve protrudes from the base so it is perhaps better to use soft surface to glue on, like a towel.</span></div><div><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdt2AehEZVIoQu_1HSPwT1hRMJVHlfQ8vEM-Zz11GlwCzaRmVU2vBmP8FlzzEL9DUexWkT8DQRF1Bn8QhZjBRLvldJajKZscIaOMlQoI6QcQ7eJOTkltuwbImHf2mbHIDp8cjju-70C38/s1600/P1060120.JPG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdt2AehEZVIoQu_1HSPwT1hRMJVHlfQ8vEM-Zz11GlwCzaRmVU2vBmP8FlzzEL9DUexWkT8DQRF1Bn8QhZjBRLvldJajKZscIaOMlQoI6QcQ7eJOTkltuwbImHf2mbHIDp8cjju-70C38/s320/P1060120.JPG" width="320" /></span></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Bottom of stem protrudes beyond the base</span></td></tr>
</tbody></table></div><div><div><span class="Apple-style-span"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">It is hard to align it with the hole before the valve sides will start catching the bladder and when they do, it is over; perhaps a helper could stretch the bladder flat when you align the valve and stick it, mine cough bit early and got slightly misaligned with the cutout.</span></span></div></div><div><span class="Apple-style-span" style="font-size: 13px;"><span class="Apple-style-span" style="font-size: medium;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></span></span></div><div><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbeAZSl4DBVie36ER_VlWnQ7m4q-B6DBq5Fqk9x7_-48k7YR6PkI7Qp46vcRq0xaDGDyd5teixosQ_YYlCWPwFGhBeIigVjQiyAWU80ed8O48dZOJuUJx2wTVFf6fRXHpD7b-gy4Nphbk/s320/P1060122.JPG" style="margin-left: auto; margin-right: auto;" width="320" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The valve glued to the bladder. </span></td></tr>
</tbody></table></div><div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The diameter of the opening in the end of strut is so small that I had to bend the base of the valve to fit it in. Then I had to push it in through with some force. Needed to get a bit medieval with it, but it worked. The rest of the way was traveled with a "string attached."</span></div></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9E_s-9NKiOuYOTYQbke3LGkTL3iZRWWQfRHBiA6CRu3YMgb1z-Ao72rmn7BYVnsLL-0zJy7HIEkHm6ktsqlCj-Yd5cTuFEhbW6P7jU1NXBTqe3saMaBA6P3ASUJAuJldH-dMYdUwucSU/s1600/P1060123.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9E_s-9NKiOuYOTYQbke3LGkTL3iZRWWQfRHBiA6CRu3YMgb1z-Ao72rmn7BYVnsLL-0zJy7HIEkHm6ktsqlCj-Yd5cTuFEhbW6P7jU1NXBTqe3saMaBA6P3ASUJAuJldH-dMYdUwucSU/s320/P1060123.JPG" width="320" /></span></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Size matters?</span></td></tr>
</tbody></table><div style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The bladder is so much longer than the original even though I followed the instructions and folded top and bottom inside to match original length. I have folded it more so it flashed with the pocket.</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguWG_eZd0NE4OVO5o9AQBSU4wwbR0FFbNaaCnFd1ylSivbW8yhpnNiP7MZ0o9h3YYb9LGSX34Hn0msgUKeH1J26bfaQHyksLWYcjwg6hGvrxh8DROEVT2kBcnDpI1_NIsm4Qzp1Bbs_1Y/s1600/P1060124.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguWG_eZd0NE4OVO5o9AQBSU4wwbR0FFbNaaCnFd1ylSivbW8yhpnNiP7MZ0o9h3YYb9LGSX34Hn0msgUKeH1J26bfaQHyksLWYcjwg6hGvrxh8DROEVT2kBcnDpI1_NIsm4Qzp1Bbs_1Y/s320/P1060124.JPG" width="320" /></span></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Too long?</span></td></tr>
</tbody></table><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The valve is a bit shallower then the original so the pipe between main the strut seems too short and bends the new valve. I wonder how it's going to work long term?.</span></div></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif; margin-left: auto; margin-right: auto;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ8LUfAtgUqMH9F2BM23HHitJoCXrgljaBj4POetBqcDaC8_olozF5NfZzeRg7lNhnsGhDgPVVmT7EZguIG5dVG01m0TEVh6ejz6KXh8MIU9dp5HXEo41SqoAN3qH9_xzbcqi1__lJX7Y/s1600/P1060126.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ8LUfAtgUqMH9F2BM23HHitJoCXrgljaBj4POetBqcDaC8_olozF5NfZzeRg7lNhnsGhDgPVVmT7EZguIG5dVG01m0TEVh6ejz6KXh8MIU9dp5HXEo41SqoAN3qH9_xzbcqi1__lJX7Y/s320/P1060126.JPG" width="320" /></a></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Too short stem?</span></td></tr>
</tbody></table><div><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">So far so good, the kite flies and makes his owner smile. The replacement was $35, a mare $15 more then the "professional" repair that failed.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: small;">References:</span></span><br />
<br />
<ul><li><a href="http://shop.airtimekite.com/"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: small;">AirTime</span></span></a></li>
<li><a href="http://www.kiteforum.com/viewtopic.php?f=1&t=2359560&view=previous"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: small;">what to use to stick it back on (forum post)</span></span></a><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: small;"> </span></span></li>
<li><a href="http://www.kitefix.com/catalog/index.php"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: small;">KiteFix</span></span></a><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: small;"> Peel2Fix system (double sided sticky tape)</span></span></li>
<li><a href="http://fixmykite.com/proddetail.asp?prod=onepumpvalve"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: small;">FixMyKite</span></span></a><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: small;"> Valves and goodies.</span></span></li>
</ul><br />
<br />
<br />
</div>Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com0tag:blogger.com,1999:blog-1760465248680296780.post-45999013837339461172009-08-05T21:51:00.000-07:002010-12-19T23:25:39.590-08:00Arduino+Accelerometer=Computerized Level Vial?<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKQOWWRFHjvo1VZDYUi9syfLajybAh4Efte6SL6qFAbjy10wGmb9DDhIpTC-rPrPQJDcVMx2vLxG_PW-5XQQVl8ytFekoxCJvFKH12Pct6Qgsiy8GQXyW9wwrI6zqC0Iasi8VK7Ja1KUM/s1600-h/PICT0704.JPG"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 200px; height: 150px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKQOWWRFHjvo1VZDYUi9syfLajybAh4Efte6SL6qFAbjy10wGmb9DDhIpTC-rPrPQJDcVMx2vLxG_PW-5XQQVl8ytFekoxCJvFKH12Pct6Qgsiy8GQXyW9wwrI6zqC0Iasi8VK7Ja1KUM/s200/PICT0704.JPG" alt="" id="BLOGGER_PHOTO_ID_5366712269773715266" border="0" /></a><span style="font-family:trebuchet ms;"><span style="font-size:130%;">What?</span><br />Ok! So I hooked up Arduino Pro Mini, an LIS302DL 3 axis accelerometer and Nokia 5110 (PCD8544 based) LCD. And What did I do with all of this? A vial level meter emulation! Right you are, not a very useful application of such a pile of technology. But so much fun! Besides, It was easier to do it this way rather then trying to melt some sand into a glass vial...<br /><br /></span><div style="text-align: center;"><br /></div><div style="text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dx2fHMlvu8QEoKbva2Tr16TYmRDkrVi6ADoutG9i95CZfn3DKlQ65NO0WHEBD27bMGqcYU23MSAjBUZlmibyw' class='b-hbp-video b-uploaded' frameborder='0'></iframe><br /></div><span style="font-family:trebuchet ms;"><span style="font-size:130%;">Really?</span><br />Yep! Both the accelerometer and LCD are SPI devices so they share MOSI, SCK and MISO (LCD does not have output). Then there are a few RESETS and SELECTs pins and this is pretty much it (plus an old cellphone battery and a charger circuit). The glue is the code.<br /></span><br /><span style="font-family:trebuchet ms;"><span style="font-size:130%;">Here!</span><br />The Arduino sketch simulates some physics rules. The LCD displays a "ball rolling in a bowl" an object rolling in a indented surface shaped like a shallow bowl. By inclining the contraption in earth gravity field, the accelerometer pick ups the motion, its readings converted into change vector acting on the virtual ball, as if someone was tilting a real bowl and hence moving the ball around. I have tossed Newton laws of motion and some mass and friction into the mix.<br /><br /><span style="font-size:130%;">Pardon my CODE</span><br />Highly experimental. The code uses 2 libraries one for accelerometer and one for LCD. Warning: Since I hate to waste space and CPU cycles, I diverged from classic Arduino singleton-object style (like in the "Serial" code-space killer). With each call to such object, there is a hidden parameter passed: the "this" pointer (and pointers on Avrs are 2 bytes). And then each function code must obey such pointer when it accesses its data members but there is never ever going to be another instance of such class (and hence another value of "this" pointer), so it is a pure waste. Granted, the source code looks more like C# or Java (Serial.println())....but I am a purist when it comes to execution...So instead I have created a static classes with only a header file to include (no cpp), perhaps I should call them "includaries"? I only wish Arduino was help while it comes to #includes, intead it is so much more (pain)!<br /><br /><span style="font-size:130%;">Accelerate!</span><br /><br />acm.h<br /><pre><br />////////////////////////////////////////////////////////////////////////////////<br />// ACceleroMeter LIS302DL<br />////////////////////////////////////////////////////////////////////////////////<br /><br />#ifdef PREDEFINED_PINS<br />// SPI bus pins<br />#define PIN_SSEL 10<br />#define PIN_SDIN 11<br />#define PIN_SDOU 12<br />#define PIN_SCLK 13<br /><br />// ACCELEROMETER<br />#define PIN_ACM_CE 7<br /><br />#define SPITRANSFER(data) { SPDR = data; while (!(SPSR & (1<<SPIF))) ; }<br />#define SPIINDATA SPDR<br /><br />void SPIInit()<br />{<br />// set direction of pins<br />pinMode(PIN_SDIN, OUTPUT);<br />pinMode(PIN_SCLK, OUTPUT);<br />pinMode(PIN_SDOU, INPUT);<br />pinMode(PIN_SSEL, OUTPUT);<br /><br />// SPCR = 01010000<br />// Set the SPCR register to 01010000<br />//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,<br />//sample on leading edge of clk,system clock/4 rate<br />SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA);<br />byte clr;<br />clr=SPSR;<br />clr=SPDR;<br />}<br /><br />#endif<br /><br />class ACM<br />{<br />public:<br /><br />static inline char ID() { return ReadReg(0x0f); }<br />static inline byte STATE() { return (byte)ReadReg(0x27); }<br />static inline char X() { return ReadReg(0x29); }<br />static inline char Y() { return ReadReg(0x2b); }<br />static inline char Z() { return ReadReg(0x2d); }<br /><br />// write to a register<br />static void WriteReg(byte reg, byte data)<br />{<br />// SS is active low<br />digitalWrite(PIN_ACM_CE, LOW);<br />// send the address of the register we want to write<br />SPITRANSFER(reg);<br />// send the data we're writing<br />SPITRANSFER(data);<br />// unselect the device<br />digitalWrite(PIN_ACM_CE, HIGH);<br />}<br /><br />// reads a register<br />static char ReadReg(byte reg)<br />{<br />WriteReg(reg|128,0);<br />return SPIINDATA;<br />}<br /><br />static void Init()<br />{<br />// CE pin, disable device<br />pinMode(PIN_ACM_CE,OUTPUT);<br />digitalWrite(PIN_ACM_CE,HIGH);<br />// start up the device<br />// this essentially activates the device, powers it on, enables all axes, and turn off the self test<br />// CTRL_REG1 set to 01000111<br />WriteReg(0x20, 0x47);<br />delay(250);<br />}<br /><br />}; // ACM<br /></pre><br /><br /><span style="font-size:130%;">Show!</span><br /><br />lcd.h<br /><pre><br />#ifdef LCD_PREDEFINED_PINS<br />#define PIN_LCD_SCE 3<br />#define PIN_LCD_RESET 4<br />#define PIN_LCD_DC 6<br /><br />// SPI bus pins<br />#define PIN_SSEL 10<br />#define PIN_SDIN 11<br />#define PIN_SDOU 12<br />#define PIN_SCLK 13<br /><br />#ifdef SPI<br />#define SPITRANSFER(data) { while (!(SPSR & (1<<SPIF))); SPDR = data; }<br />#define SPIINDATA SPDR<br />#else<br />#define SPITRANSFER(data) shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data)<br />#define SPIINDATA 0<br />#endif<br /><br />#endif<br /><br />class LCD<br />{<br />public:<br />enum<br />{<br />XM=84,<br />YM=48<br />};<br /><br />static void Fill(byte pattern, int count)<br />{<br />digitalWrite(PIN_LCD_SCE, LOW);<br />while(count-->0)<br />{<br /> SPITRANSFER(pattern);<br />}<br />digitalWrite(PIN_LCD_SCE, HIGH);<br />}<br /><br />static void Clear()<br />{<br />Fill(0, XM * YM / 8);<br />}<br /><br />static void Char(byte character)<br />{<br />static const byte ASCII[][5] =<br />{<br /> {0x00, 0x00, 0x00, 0x00, 0x00} // 20<br />,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !<br />,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 "<br />,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #<br />,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $<br />,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %<br />,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &<br />,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 '<br />,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (<br />,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )<br />,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *<br />,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +<br />,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,<br />,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d -<br />,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .<br />,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f /<br />,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0<br />,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1<br />,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2<br />,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3<br />,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4<br />,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5<br />,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6<br />,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7<br />,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8<br />,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9<br />,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a :<br />,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;<br />,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c <<br />,{0x14, 0x14, 0x14, 0x14, 0x14} // 3d =<br />,{0x00, 0x41, 0x22, 0x14, 0x08} // 3e ><br />,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?<br />,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @<br />,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A<br />,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B<br />,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C<br />,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D<br />,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E<br />,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F<br />,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G<br />,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H<br />,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I<br />,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J<br />,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K<br />,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L<br />,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M<br />,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N<br />,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O<br />,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P<br />,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q<br />,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R<br />,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S<br />,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T<br />,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U<br />,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V<br />,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W<br />,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X<br />,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y<br />,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z<br />,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [<br />,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c ¥<br />,{0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]<br />,{0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^<br />,{0x40, 0x40, 0x40, 0x40, 0x40} // 5f _<br />,{0x00, 0x01, 0x02, 0x04, 0x00} // 60 `<br />,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a<br />,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b<br />,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c<br />,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d<br />,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e<br />,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f<br />,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g<br />,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h<br />,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i<br />,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j<br />,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k<br />,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l<br />,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m<br />,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n<br />,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o<br />,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p<br />,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q<br />,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r<br />,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s<br />,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t<br />,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u<br />,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v<br />,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w<br />,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x<br />,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y<br />,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z<br />,{0x00, 0x08, 0x36, 0x41, 0x00} // 7b {<br />,{0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |<br />,{0x00, 0x41, 0x36, 0x08, 0x00} // 7d }<br />,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ?<br />,{0x78, 0x46, 0x41, 0x46, 0x78} // 7f ?<br />,{0xff, 0x81, 0x81, 0x81, 0xff} // 80 frame<br />,{0x18, 0x24, 0x42, 0x24, 0x18} // 81 diamont<br />};<br /><br /> digitalWrite(PIN_LCD_SCE, LOW);<br /> if( character < 0x20 || character-0x20 >= sizeof(ASCII)/5 )<br /> {<br /> for (byte index = 5+2; index > 0 ; index--)<br /> {<br /> SPITRANSFER(character);<br /> }<br /> }<br /> else<br /> {<br /> SPITRANSFER(0x00);<br /> for (byte index = 0; index < 5; index++)<br /> {<br /> byte data = ASCII[character - 0x20][index];<br /> SPITRANSFER(data);<br /> }<br /> SPITRANSFER(0x00);<br /> }<br /> digitalWrite(PIN_LCD_SCE, HIGH);<br />}<br /><br />static void Init(void)<br />{<br />pinMode(PIN_LCD_SCE, OUTPUT);<br />pinMode(PIN_LCD_RESET, OUTPUT);<br />pinMode(PIN_LCD_DC, OUTPUT);<br />digitalWrite(PIN_LCD_DC,HIGH);<br />digitalWrite(PIN_LCD_SCE,HIGH);<br />digitalWrite(PIN_LCD_RESET, LOW);<br />digitalWrite(PIN_LCD_RESET, HIGH);<br />delay(10);<br />#if 1<br />Cmd( 0x21 ); // LCD Extended Commands.<br />Cmd( 0xC8 ); // Set LCD Vop (Contrast).<br />Cmd( 0x06 ); // Set Temp coefficent.<br />Cmd( 0x13 ); // LCD bias mode 1:48.<br />#endif<br />Cmd( 0x20 ); // LCD Standard Commands, Horizontal addressing mode.<br />Cmd( 0x0C ); // LCD in normal mode.<br />// Cmd( 0x0D ); // LCD in reverse mode<br />}<br /><br />static void Goto(byte row,byte col)<br />{<br />digitalWrite(PIN_LCD_DC, LOW);<br />digitalWrite(PIN_LCD_SCE, LOW);<br />SPITRANSFER(0x40|row); //Cmd(0x40|row);<br />SPITRANSFER(0x80|col); // Cmd(0x80|col);<br />digitalWrite(PIN_LCD_SCE, HIGH);<br />digitalWrite(PIN_LCD_DC, HIGH);<br />}<br /><br />static void Str(char *characters)<br />{<br />while (*characters)<br />{<br /> Char(*characters++);<br />}<br />}<br /><br />template<unsigned base><br />static void Num(unsigned num,char digits=0)<br />{<br /> unsigned div = 1;<br /> // find biggest power of base that is not greater then num<br /> // keep going when more digits are requested<br /> while( true )<br /> {<br /> unsigned newdiv = div*base;<br /> if( newdiv < div ) break; // overflow<br /> digits--;<br /> if( newdiv > num && digits<=0) break; // end<br /> div = newdiv;<br /> }<br /> while( div > 0 )<br /> {<br /> unsigned dig = num / div;<br /> char c = dig < 10 ? '0'+dig : 'A'+dig-10;<br /> Char(c);<br /> num-=dig*div;<br /> div/=base;<br /> }<br />}<br /><br />template<unsigned base><br />static void Num(int num,char digits)<br />{<br /> if( num<0 )<br /> {<br /> Char('-');<br /> num=-num;<br /> digits--;<br /> }<br /> Num<base>((unsigned)num,digits);<br />}<br /><br />private:<br />static void Cmd(byte cmd)<br />{<br /> digitalWrite(PIN_LCD_DC, LOW);<br /> digitalWrite(PIN_LCD_SCE, LOW);<br /> SPITRANSFER(cmd);<br /> digitalWrite(PIN_LCD_SCE, HIGH);<br /> digitalWrite(PIN_LCD_DC, HIGH);<br />}<br />};<br /></pre><br /><span style="font-size:130%;">The MAIN feature</span><br /><pre><br />// SPI bus pins<br />#define PIN_SSEL 10<br />#define PIN_SDIN 11<br />#define PIN_SDOU 12<br />#define PIN_SCLK 13<br /><br />#define SPITRANSFER(data) { SPDR = data; while (!(SPSR & (1<<SPIF))) ; }<br />#define SPIINDATA SPDR<br /><br />////////////////////////////////////////////////////////////////////////////////<br /><br />void SPIInit()<br />{<br />// set direction of pins<br />pinMode(PIN_SDIN, OUTPUT);<br />pinMode(PIN_SCLK, OUTPUT);<br />pinMode(PIN_SDOU, INPUT);<br />pinMode(PIN_SSEL, OUTPUT);<br /><br />// SPCR = 01010000<br />// Set the SPCR register to 01010000<br />//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,<br />//sample on leading edge of clk,system clock/4 rate<br />SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA);<br />byte clr;<br />clr=SPSR;<br />clr=SPDR;<br />}<br /><br />// ACCELEROMETER<br />#define PIN_ACM_CE 7<br />#include "{yourpathhere}\accelerometer.h"<br /><br />// LCD<br />#define PIN_LCD_SCE 3<br />#define PIN_LCD_RESET 4<br />#define PIN_LCD_DC 6<br />#include "{yourpathhere}\lcd.h"<br /><br /><br />////////////////////////////////////////////////////////////////////////////////////////////<br />////////////////////////////////////////////////////////////////////////////////////////////<br />////////////////////////////////////////////////////////////////////////////////////////////<br /><br />void setup(void)<br />{<br />Serial.begin(9600);<br /><br />// set direction of pins<br />pinMode(PIN_SDIN, OUTPUT);<br />pinMode(PIN_SCLK, OUTPUT);<br />pinMode(PIN_SDOU, INPUT);<br />pinMode(PIN_SSEL, OUTPUT);<br /><br />pinMode(PIN_ACM_CE,OUTPUT);<br />digitalWrite(PIN_ACM_CE, HIGH);<br />pinMode(PIN_LCD_SCE,OUTPUT);<br />digitalWrite(PIN_LCD_SCE, HIGH);<br /><br />SPIInit();<br /><br />LCD::Init();<br />LCD::Clear();<br />ACM::Init();<br />Serial.println(ACM::ID(),HEX);<br />Serial.println(ACM::STATE(),HEX);<br />Serial.println("=============");<br />}<br /><br /><br />const byte BALLSIZE = 4;<br /><br />void DrawBall(byte x, byte y, byte erase)<br />{<br />byte row = y / 8;<br />byte shift = y % 8;<br />unsigned pattern = (1<<BALLSIZE)-1;<br />pattern <<= shift;<br />byte f;<br />f = pattern & 0xFF;<br />if( f )<br />{<br />LCD::Goto(row,x);<br />LCD::Fill(erase ? 0 : f, BALLSIZE);<br />}<br />f = pattern >> 8;<br />if( f )<br />{<br />LCD::Goto(row+1,x);<br />LCD::Fill(erase ? 0 : f, BALLSIZE);<br />}<br />}<br /><br />static byte curx = 0;<br />static byte cury = 0;<br /><br />void MoveBall(byte x, byte y)<br />{<br />if( curx != x || cury != y )<br />{<br />DrawBall(curx,cury,1);<br />curx = x; cury=y;<br />DrawBall(curx,cury,0);<br />}<br />}<br /><br />//////////////////////////////////////////////////////////////////////////////////////////<br /><br />// all units are SI : meters, seconds etc.<br /><br />// G force (earth gravity)<br />const float G = 9.81; // m/s2<br /><br />// pixel size<br />const float pixsize = 3e-2/LCD::XM; // in meters =~ width(3cm)/numpixX<br />// ball size<br />const float ballsize = BALLSIZE*pixsize;<br />const float xsize = LCD::XM * pixsize;<br />const float ysize = LCD::YM * pixsize;<br />float x=float(LCD::XM/2)*pixsize;<br />float y=float(LCD::YM/2)*pixsize;<br />float px=float(LCD::XM/2)*pixsize;<br />float py=float(LCD::YM/2)*pixsize;<br />float vx=0;<br />float vy=0;<br />float prevTime = 0;<br /><br />float elapsed()<br />{<br />if( prevTime == 0 ) prevTime = float(1e-3*millis());<br />float time = float(1e-3*millis());<br />float delta = time - prevTime;<br />prevTime = time;<br />return delta;<br />}<br /><br />inline float sign(float f)<br />{<br />return f > 0 ? 1 : (f < 0 ? -1 : 0);<br />}<br /><br /><br />float ax = 0;<br />float ay = 0;<br />float az = 0;<br /><br />float azx = 0;<br />float azy = 0;<br />float azz = 0;<br /><br /><br />void zero()<br />{<br />ax=ay=az=0;<br />azx=azy=azz=0;<br />for( byte n = 0; n < 4; n++ )<br />{<br />measure();<br />}<br />azx=ax;<br />azy=ay;<br />azz=az;<br />}<br /><br />void measure()<br />{<br />const float filtercoef = 0.25;<br />ax = filtercoef*(G/64.0)*float(ACM::X())+(1-filtercoef)*ax;<br />ay = filtercoef*(G/64.0)*float(ACM::Y())+(1-filtercoef)*ay;<br />az = filtercoef*(G/64.0)*float(ACM::Z())+(1-filtercoef)*az;<br />}<br /><br />void loop(void)<br />{<br />zero();<br />while(1)<br />{<br />#if 0<br />// LIS302DL<br />char ax = ACM::X();<br />char ay = ACM::Y();<br />char az = ACM::Z();<br />char accx = map(ax,-64,64,0,LCD::XM);<br />LCD::Goto(3,0);LCD::Fill(0,accx-2);LCD::Fill(0xFF,4);LCD::Fill(0,LCD::XM-accx-4);<br />char accy = map(ay,-64,64,0,LCD::XM);<br />LCD::Goto(4,0);LCD::Fill(0,accy-2);LCD::Fill(0xFF,4);LCD::Fill(0,LCD::XM-accy-4);<br />char accz = map(az,-64,64,0,LCD::XM);<br />LCD::Goto(5,0);LCD::Fill(0,accz-2);LCD::Fill(0xFF,4);LCD::Fill(0,LCD::XM-accz-4);<br />#endif<br /><br />float dt = elapsed();<br /><br />#if 0<br />const float refrat = -1;<br />if( vx == 0 ) vx = 10*pixsize/1; // 10 pixels per second<br />if( vy == 0 ) vy = 10*pixsize/1; // 10 pixels per second<br />x += vx * dt;<br />y += vy * dt;<br />if( x < 0 ) { x = 0; vx = refrat * vx; }<br />if( x >= xsize-ballsize ) { x = xsize-ballsize; vx = refrat * vx; }<br />if( y < 0 ) { y = 0; vy = refrat * vy; }<br />if( y >= ysize-ballsize ) { y = ysize-ballsize; vy = refrat * vy; }<br />#else<br />measure();<br />// apply gravity the display's y axis is a z axis of acceleromiter due to mounting direction<br />vx += (ax-azx)*dt;<br />vy += (az-azz)*dt;<br />// apply center pull this emulates a hiperbol shape bowl-like dish in which the ball rolls<br />const float fudge = 0.2;<br />vx += -fudge*G*(x-(xsize/2-ballsize/2))/xsize*dt;<br />vy += -fudge*G*(y-(ysize/2-ballsize/2))/ysize*dt;<br />// vx += -0.5*(x>xsize/2?1:-1)*dt;<br />// vy += -0.5*(y>ysize/2?1:-1)*dt;<br />// apply friction<br />vx += -0.1*vx;<br />vy += -0.1*vy;<br />// move with speed<br />x += vx * dt;<br />y += vy * dt;<br />// bounce off walls<br />const float refrat = 0.9; // bounce reflection ratio (== 1 for perfect bounce)<br />if( x < 0 ) { x = 0; vx = refrat * vx; }<br />if( x >= xsize-ballsize ) { x = xsize-ballsize; vx = refrat * vx; }<br />if( y < 0 ) { y = 0; vy = refrat * vy; }<br />if( y >= ysize-ballsize ) { y = ysize-ballsize; vy = refrat * vy; }<br />// zero speed if we are trully not moving<br />if( abs(px - x) < 1e-10 ) vx = 0;<br />if( abs(py - y) < 1e-10 ) vy = 0;<br />px = x;<br />py = y;<br />#endif<br /><br />byte bx = (byte)(x/pixsize);<br />byte by = (byte)(y/pixsize);<br />MoveBall(bx,by);<br />#if 1<br />Serial.println(dt);<br />Serial.println(ax);<br />Serial.println(az);<br />Serial.println(vx);<br />Serial.println(vy);<br />Serial.println(G*(x-(xsize/2-ballsize/2))/xsize*dt);<br />Serial.println(G*(y-(ysize/2-ballsize/2))/ysize*dt);<br />Serial.println();<br />#endif<br />// LCD::Goto(0,0);LCD::Num<10>(bx);<br />// LCD::Goto(0,LCD::XM/2);LCD::Num<10>(by);<br />delay(20);<br />}<br />}<br /></pre><br /></span>Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com2tag:blogger.com,1999:blog-1760465248680296780.post-66982092667313884262009-08-02T17:00:00.000-07:002010-12-19T23:25:39.591-08:00Arduino IR Receiver with Interrupts<span style="font-family:trebuchet ms;"><br /><br /><span style="font-size:130%;">Infra Red Receiver with the use of Pin Change Interrupt</span><br /><br />Infrared remote control receiver implemented using pin change interrupt. This implementation allows the main loop to perform other tasks while the receiver code collects incoming IR message bits in the background. This method was used to receive IR control message send to the iSOBOT robot from its remote. It is runnin on Arduino Mini Pro with AVR m168 CPU.<br /><br /><span style="font-size:130%;">Problem Definition</span><br /><br />The IR remote receiver is observing output of the IR sensor/demodulator which signals presents or absents of modulated IR. The output of the sensor is connected to a pin of the CPU which is then read by the software and interpreted by as bits of the message. To recognize the beginning of the message and to interpret the waveform generated by, the code has to measure time between signal transition. Beginning of the message is signaled as 2.5ms burst of IR while 0 and 1 are coded as length of silence between 0.5ms IR bursts (0- 0.5 ms silence while 1 is 1ms silence). See <a href="http://profmason.com/?p=627">IR waveforms</a> and <a href="http://minkbot.blogspot.com/2009/08/isobot-infrared-remote-protocol-hack.html">protocol description.</a><br /><br /><span style="font-size:130%;">Classic Approach</span><br /><br /><span style="font-size:100%;">The code below is uses a polling approach. When it waits for the signal change it simply reads (polls) the signal until a change is observed. While this is straight forward and very simply, it occupies the CPU in 100%. Here is an implementation of example:<br /></span><br /><br /><pre><br />// helper functions<br /><br />unsigned long elapsedSince(unsigned long since, unsigned long now)<br />{<br />return since &lh; now ? now-since : 0xFFFFFFFFUL - (now - since);<br />}<br /><br />unsigned long elapsedSince(unsigned long since)<br />{<br />return elapsedSince( since, micros() );<br />}<br /><br />// iSOBOT IR protocol timing<br />#define TimeStart 2500<br />#define TimeZero 500<br />#define TimeOne 1000<br />#define TimeOff 500<br /><br />// check if the time was in range +/- 25%<br />#define IS_X(t,x) ((t > 3*(x)/4) && (t < 5*(x)/4))<br />#define IS_0(t) IS_X(t,TimeZero)<br />#define IS_1(t) IS_X(t,TimeOne)<br />#define IS_S(t) IS_X(t,TimeStart)<br />#define IS_O(t) IS_X(t,TimeOff)<br /><br />//////////////////////////////////////////////////////////////////////<br />// polling/blocking version of IR receiver<br />//////////////////////////////////////////////////////////////////////<br /><br />//////////////////////////////////////////////////////////////////////<br />// waits for IR carrier transitions (on->off & off->on)<br />// returns duration of the specified state (HIGH->IR transmitting; LOW->IR off)<br />// returns 0 if timeout<br />unsigned irRecvSignal(byte waitFor)<br />{<br />while(digitalRead(PIN_IR)==(waitFor==LOW?HIGH:LOW)) {};<br />unsigned long start = micros();<br />while(digitalRead(PIN_IR)==waitFor) {};<br />return elapsedSince(start);<br />}<br /><br />////////////////////////////////////////////////////////////////////////<br />// receives all 22 bits of the messagge<br />long irRecv()<br />{<br />Serial.println("Waiting...");<br />unsigned time = irRecvSignal(LOW);<br />if( !IS_S(time) )<br />{<br />Serial.println("False Start");<br />Serial.println(time);<br />return 0;<br />}<br />long bits = 0;<br />byte len = 22;<br />for(int i = 0; i < len; i++ )<br />{<br />bits <<= 1;<br />time = irRecvSignal(HIGH);<br />if( IS_1(time) )<br />{<br /> bits |= 1;<br />}<br />else if( IS_0(time) )<br />{<br /> bits |= 0;<br />}<br />else<br />{<br /> Serial.println("Bad Bit");<br /> Serial.println(time);<br /> return 0;<br />}<br />// check type of message (when recved) to guess the message length (either 22 ot 30 bits)<br />if( bit == 3 )<br />{<br /> byte msgtype = bits & 0x3;<br /> if( msgtype == 0 ) len = 30;<br />}<br />}<br />return bits;<br />}<br /></pre><br /><br />The jest of the polling happens in the loops in irRecvSignal(byte waitFor) function.<br />The time duration is measured with Arduino's time function micros() returning number of microseconds since the CPU was started. Note that the number of microseconds will wrap around, which I am compensating for in elapsedSince() function.<br /><br />When I want to receive a message I just call irRecv().<br /><br /><pre><br />void loop()<br />{<br />...<br />long msg = irRecv();<br />...<br />}<br /></pre><br /><br />This call will block until a message is received. Hence, nothing else in the main loop will be executed while I wait for IR message (ie wait for the irRecv() to return).<br /><br /><span style="font-size:130%;">Interrupts</span><br /><br />So, I have one CPU here but I'd like to perform more then one task at a time. One way is to "distract" or "interrupt" the main code and "switch" to something else for a moment is to you interrupts. Since the IR receiver cares only about changes in the IR signal and these changes are relatively infrequent, the cost of interrupting the main task will be small. At the worst case the IR signal changes every 500us which on 16MHz CPU AVR allows for about 8000 instructions to be executed in between. Granted, there is some overhead cost of interrupting (multitasking is hard for humans as well) but it should be rather small esp. since in this case the IR message are also sent infrequently.<br /><br /><span style="font-size:130%;">Solution</span><br /><br />Ok, so here is the code I came up with. It is more complicated than the polling version. Since the interrupt code is/should be active only for brief moments, the state of receiving a message must be preserved between its actions. I used a state machine to implement this functionality (by "state machine" I mean that one single function is invoke on IR signal change but this function "switches" into different state depending on its current state and elapsed time since last invocation).<br /><br /><pre><br /><br />// pin state change interrupt based IR receiver<br />// observing the IR pin changes, measure time between interrupts<br />// use state machine to decide what to do<br /><br />enum<br />{<br />ISR_IDLE, // nothing is/was happening (quiet)<br />ISR_START, // start of sequence, was waiting for a header signal<br />ISR_BIT_ON, // transsmitting a bit (IR carrier turned on)<br />ISR_BIT_OFF // in an OFF bit slot (IR carrier turned off)<br />}<br />isrState = ISR_IDLE;<br /><br />unsigned long isrLastTimeStamp;<br />unsigned long isrRcvCmd;<br />unsigned long isrNewCmd;<br />byte isrBitLen = 22;<br />byte isrBitCnt;<br /><br /><br />ISR( PCINT2_vect )<br />{<br />// PIN_IR == #2 --> PD2;<br />// receiving a modulated IR signal makes the pin go low (active low)<br />byte transmitting = (PIND & (1<<2)) == 0;<br /><br />// compute elapsed time since last change<br />unsigned elapsed;<br />{<br /> unsigned long timeStamp = micros();<br /> elapsed = elapsedSince(isrLastTimeStamp,timeStamp);<br /> isrLastTimeStamp = timeStamp;<br />}<br />switch( isrState )<br />{<br /> case ISR_IDLE :<br /> if( transmitting ) isrState = ISR_START;<br /> break;<br /> case ISR_START:<br /> isrBitCnt = 0;<br /> isrNewCmd = 0;<br /> isrBitLen = 22;<br /> if( !transmitting && IS_S(elapsed) )<br /> isrState = ISR_BIT_ON; // bits are now rolling<br /> else<br /> isrState = ISR_IDLE; // wrong timing of start or pin state<br /> break;<br /> case ISR_BIT_ON:<br /> if( transmitting )<br /> {<br /> isrState = ISR_BIT_OFF;<br /> isrNewCmd <<= 1;<br /> isrBitCnt ++;<br /> if( IS_1(elapsed) )<br /> {<br /> isrNewCmd |= 1;<br /> }<br /> else if( IS_0(elapsed) )<br /> {<br /> // isrNewCmd |= 0;<br /> }<br /> else<br /> isrState = ISR_START; // bad timing, start over<br /> if( isrBitCnt == 7 ) // we have received 6 bit header (now expecting 7th bit)<br /> {<br /> isrBitLen = (isrNewCmd & (3<<3)) == 0 ? 30 : 22; // 2 vs 3 byte commands<br /> }<br /> }<br /> else isrState = ISR_IDLE; // bad state (should never get here...)<br /> break;<br /> case ISR_BIT_OFF:<br /> if( !transmitting && IS_O(elapsed) )<br /> {<br /> if( isrBitCnt == isrBitLen ) // is this the end?<br /> {<br /> isrState = ISR_IDLE;<br /> isrRcvCmd = isrNewCmd;<br /> }<br /> else <br /> isrState = ISR_BIT_ON; // keep bits rolling<br /> }<br /> else<br /> if( IS_S(elapsed) )<br /> isrState = ISR_START;<br /> else<br /> isrState = ISR_IDLE;<br /> break;<br />}<br />}<br /></pre><br /><br />To link a function to an interrupt I used <pre>ISR( PCINT2_vect )</pre> (assigns it to the INT2 interrupt vector which is linked to the pin I used for IR signal).<br /><br /><span style="font-size:130%;">And the rest of it</span><br /><br />Here is a function returning a new message:<br /><br /><pre><br />long irRecv()<br />{<br /> byte oldSREG = SREG;<br /> cli();<br /> long cmd = isrRcvCmd;<br /> isrRcvCmd = 0;<br /> SREG = oldSREG;<br /> return cmd;<br />}<br /></pre><br /><br />This is a non-blocking function. If there was nothing, it returns 0 (there is no message that would result in a 0). When a message code is read, a 0 is stuffed back into isrRcvCmd to clear it so next time I read it I do not get a repeat. I also turn off interrupts for the duration of the "read and zero" of isrRcvCmd so I do not conflict with the interrupt code "interrupting" my read. Note that: <pre>long cmd = isrRcvCmd;</pre> is not "atomic" ie it consists of several CPU instructions and hence it may be interrupted in the middle and ended up returning an inconsistent value.<br /><br />So now I can really do more stuff in main loop:<br /><br /><pre><br />void loop<br />{<br /> unsigned long rcv = irRecv();<br /> if(rcv)<br /> {<br /> // got a message<br /> Serial.print("recv ");<br /> Serial.println(rcv,HEX);<br /> } <br /> Serial.print('.');<br />... do whatever you like<br />}<br /></pre><br /><br /><span style="font-size:130%;">Configuring Interrupt</span><br />I have connected the IR sensor to pin D2 (#2 in Arduino convention). The pin change interrupts are not enabled by default so I needed to configure it in setup:<br /><br /><pre><br />void setup()<br />{<br />...<br />PCICR |= 4; // enable PCIE2 which services PCINT18<br />PCMSK2 |= 4; // enable PCINT18 --> Pin Change Interrupt of PD2<br />...<br />}<br /></pre><br /><br /></span>Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com3tag:blogger.com,1999:blog-1760465248680296780.post-33449934941052680042009-08-01T10:36:00.000-07:002010-12-19T23:25:39.592-08:00iSobot Infrared Remote Protocol HackThe iSOBOT IR protocol details are described here. I figured out all details to be able to create complete messages,even ones not originally send by the remote (some diagnostic codes and prompts).<br /><br /><span style="font-size:130%;"><span style="font-family:trebuchet ms;">History</span></span><br />iSobot is a lot of fun. It has a bunch of preprogrammed, often very funny moves. Kudos to TOMMY enginieers. I envy them their fun at work! But, all in all, iSobot is rather dummy.It does not have any sensors to be autonomous. The only sensors it posseses are microphone for voice commands and 1 axis gyro. So, it did not take much time for the people to want to hack it.<br /><br />See some iSOBOT hacking links (with thanks to authors for their work):<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhos9cndRQ6ySSDA2F3XxynBQ6Uh5lOdsL5rCOgb4VRA8lRigebHwEbkQ8O4s_5EoXsPe3PGkrDpidxnUka_rP_27Je4ZT3i92fZStAFTYoZ73bzwDUsbMlrqC2zv3KRfg_WyeWVdH45CM/s1600-h/PICT0698.JPG"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 200px; height: 150px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhos9cndRQ6ySSDA2F3XxynBQ6Uh5lOdsL5rCOgb4VRA8lRigebHwEbkQ8O4s_5EoXsPe3PGkrDpidxnUka_rP_27Je4ZT3i92fZStAFTYoZ73bzwDUsbMlrqC2zv3KRfg_WyeWVdH45CM/s200/PICT0698.JPG" alt="" id="BLOGGER_PHOTO_ID_5365088670107356706" border="0" /></a><br /><a href="http://www.electronicsinfoline.com/New/Robotics/i-sobot-hacking-resources.html">HACKING RESOURCES</a><br /><a href="http://robot.watch.impress.co.jp/cda/column/2007/11/08/731.html">ANATHOMY</a><br /><a href="http://i-sobothacking.blogspot.com/">SERVOS</a><br /><a href="http://profmason.com/?p=627">IR SIGNALING</a><br /><a href="http://www.youtube.com/watch?v=HR84q3zRKT8">TOTAL (HEADLESS) HACK</a><br /><a href="http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1237771631">IRCONTROLLED BACKPACK</a><br /><br />For me the IR control was the way to go, as I did not have time to do a total hack (replacing iSOBOT's brains) and the build-in stuff is fun anyway. I just wanted to add an alter-ego personality...I ended up replacing the 3 AAA batteries with a LiIon 3.7V battery (S007 from my broken Panasonic camera) and Arduino Pro Mini CPU. A CPU pin is directly connected to the iSOBOT IR receiver output (as the IR receiver device has open-collector output it was rather simple).<br /><br /><span style="font-size:130%;"><span style="font-family:trebuchet ms;">IR Signaling</span></span><br />The iSobot IR remote is using fairly simple protocol. In short, the IR is modulated with 38kHz. Each message starts with a longer IR burst of ~2.5ms, followed by actual payload bits. The bit value is coded as length of silence period between the 0.5ms IR 38KHz bursts. 1 is a 1ms silence and 0 is 0.5 ms silence. Initially I used Arduino "logic analyzer" to read the bits and create list of messages. Next I tried to find any rhyme or reason to all the codes and here is the result.<br /><br /><span style=";font-family:trebuchet ms;font-size:130%;" >General Message Format</span><br /><br /><span style="font-family:courier new;"><header><byte1><byte2>[HEADER][BYTE1][BYTE2]{[BYTE3]}</byte2></byte1></header></span><br /><br />[<span style="font-family:courier new;">HEADER]</span><header:6>is 6 bits of:<br /></header:6><ul><li><header:6><span style="font-family:courier new;"><channel:1></channel:1>[CHANNEL:1]</span> 0 - A; 1 - B</header:6></li><li><header:6><span style="font-family:courier new;"><msgtype:2></msgtype:2></span><span style="font-family:courier new;">[TYPE:2]</span> 00 - 3 byte message used for arms control; 01 - 2 byte message (used for most commands;</header:6></li><li><header:6><span style="font-family:courier new;"><checksum:3></checksum:3></span> <span style="font-family:courier new;">[CHECKSUM:3]</span> checksum of the entire message (see below)</header:6></li></ul><br /><header:6>So here are the 2 types of messages:<br /><span style="font-family:courier new;"><ch:1><type:2></type:2></ch:1></span><pre>[CH:1][TYPE:2 = 00][CHECK:3][CMD1:8][CMD2:8][CMD3:8]<br />[CH:1][TYPE:2 = 01][CHECK:3][CMD:8][PARAM:8]<br /></pre>For message type 01 (2 byte) the second byte is often zero, except when used sometimes for parameters e.g. in joystick movement command (PARAM is always 0x03, do not know what this means) and for configuration command 0xD3 where the 4 lowest bits of PARAM are Lon:1,Loff:1,S:1,V:1 where L-light, V-voice, S-sound.<br /><br /><span style="font-size:130%;"><span style="font-family:trebuchet ms;">The Checksum</span></span><br /><br />This was the toughest part to decipher. It ended up logical and simple.<br />First sum all the bytes (including header stored as separate byte).<br />Then sum up the result, 3 bits at a time and use lower 3 bit of this sum as a CHECKSUM.<br /><br />So here is a C code snaplet (Arduino):<br /><span style="font-family:courier new;"><br /><pre><br />byte computeCheckSum( byte hdr, byte cmd1, byte cmd2, byte cmd3 )<br />{<br />// first sum up all bytes<br />byte s = hdr + cmd1 + cmd2 + cmd3;<br />// then sum up the result, 3 bits at a time<br />s = (s & 7) + ((s >> 3) & 7) + (s >> 6) & 7;<br />// return 3 lower bits of the sum<br />return s & 7;<br />}<br /></pre></span><br /><span style="font-size:130%;"><span style="font-family:trebuchet ms;">Command Notes</span></span><br /><br />Observations:<br /></header:6><ul><li><header:6> commands are interrupt-able but each expect to start from HP (home position)</header:6></li><li><header:6>some commands will reposition legs, while some will not so interesting hybrids can result e.g. try EAGLE for 3 seconds and then sent AIRDRUM - iSOBOT will play drums while standing on one leg (but this will not work with AIRGUITAR as it will reset legs).</header:6></li></ul><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dy21VKT1lIa8kGj9bMshZ9HKY1jaxl8Q6wsKoXOIPL8iNgLnBKr5X21gJheElFS-FHhG2QnMgDAbBuVG9Rd3A' class='b-hbp-video b-uploaded' frameborder='0'></iframe><br /><header:6>Movement (left joystick)<br /><pre>FWRD 0.01.101.10110111.00000011<br />BWRD 0.01.110.10111000.00000011<br />LEFT 0.01.001.10111011.00000011<br />RGHT 0.01.010.10111100.00000011<br />FWLT 0.01.111.10111001.00000011<br />FWRT 0.01.000.10111010.00000011<br />BKRT 0.01.101.10111110.00000011<br />BKLT 0.01.100.10111101.00000011<br />STOP 0.01.101.11010111.00000000 (joystick nutral)<br /></pre>These are repeated when joystick is pushed. Need to try to mess with the parameters...<br /><br />Arms (right joystick+front buttons)<br /><pre><br />NOIMP 1.00.010.10000100.10000000.10000000<br />NOIMP 1.01.000.11010110.00000000 (locked)<br />END 1.01.001.11010111.00000000<br />END 1.01.001.11010111.00000000 (locked-same as normal)<br /><br />RUP 1.00.000.10000111.10000010.10000000<br />RDW 1.00.000.10000000.10000010.10000000<br />RRT 1.00.110.10000100.10000000.11110000<br />RLT 1.00.010.10000100.10000000.10000000<br />LUP 1.00.110.10000100.11110000.10000000<br />LDW 1.00.010.10000100.00010000.10000000<br />LRT 1.00.101.11101100.10000000.10000000<br />LLT 1.00.001.00001100.10000000.10000000<br /></pre>NOIMP is send when joystick is not pushed. Now, any patterns here? Why these needed 3 bytes? Perhaps they drive the servos directly...<br /><br /><span style="font-size:130%;"><span style="font-family:trebuchet ms;">List of Commands</span></span><br /><br /><pre><br />#define CMD_RC 0x07<br />#define CMD_PM 0x08<br />#define CMD_SA 0x09<br />#define CMD_VC 0x0a<br />#define CMD_1P 0x13<br />#define CMD_2P 0x14<br />#define CMD_3P 0x15<br />#define CMD_4P 0x16<br />#define CMD_11P 0x17<br />#define CMD_12P 0x18<br />#define CMD_13P 0x19<br />#define CMD_14P 0x1a<br />#define CMD_21P 0x1b<br />#define CMD_22P 0x1c<br />#define CMD_23P 0x1d<br />#define CMD_24P 0x1e<br />#define CMD_31P 0x1f<br />#define CMD_32P 0x20<br />#define CMD_34P 0x21<br />#define CMD_1K 0x22<br />#define CMD_2K 0x23<br />#define CMD_3K 0x24<br />#define CMD_4K 0x25<br />#define CMD_11K 0x26<br />#define CMD_12K 0x27<br />#define CMD_13K 0x28<br />#define CMD_14K 0x29<br />#define CMD_31K 0x2a<br />#define CMD_42K 0x2b<br />#define CMD_21K 0x2c<br />#define CMD_22K 0x2d<br />#define CMD_23K 0x2e<br />#define CMD_24K 0x2f<br />#define CMD_31K 0x30<br />#define CMD_34K 0x31<br />#define CMD_3G 0x32<br />#define CMD_2G 0x33<br />#define CMD_3G 0x34<br />#define CMD_4G 0x35<br />#define CMD_11G 0x36<br />#define CMD_12G 0x37<br />#define CMD_13G 0x38<br />#define CMD_14G 0x39<br />#define CMD_21G 0x3a<br />#define CMD_22G 0x3b<br />#define CMD_23G 0x3c<br />#define CMD_A 0x3d<br />#define CMD_B 0x3e<br />#define CMD_1A 0x3f<br />#define CMD_2A 0x40<br />#define CMD_2A 0x41<br />#define CMD_3A 0x42<br />#define CMD_4A 0x43<br />#define CMD_11A 0x44<br />#define CMD_12A 0x45<br />#define CMD_13A 0x46<br />#define CMD_14A 0x47<br />#define CMD_21A 0x48<br />#define CMD_22A 0x49<br />#define CMD_23A 0x4a<br />#define CMD_32A 0x4b<br />#define CMD_31A 0x4c<br />#define CMD_32A 0x4d<br />#define CMD_41A 0x4e<br />#define CMD_42A 0x4f<br />#define CMD_43A 0x50<br />#define CMD_111A 0x51<br />#define CMD_222A 0x52<br />#define CMD_333A 0x53<br />#define CMD_11B 0x54<br />#define CMD_12B 0x55<br />#define CMD_13B 0x56<br />#define CMD_14B 0x57<br />#define CMD_31B 0x58<br />#define CMD_22B 0x59<br />#define CMD_23B 0x5a<br />#define CMD_24B 0x5b<br />#define CMD_31B 0x5c<br />#define CMD_32B 0x5d<br />#define CMD_33B 0x5e<br />#define CMD_234B 0x5f<br />#define CMD_41B 0x60<br />#define CMD_42B 0x61<br />#define CMD_43B 0x62<br />#define CMD_44B 0x63<br />#define CMD_112A 0x65<br />#define CMD_113A 0x66<br />#define CMD_114A 0x67<br />#define CMD_124A 0x6b<br />#define CMD_131A 0x6c<br />#define CMD_132A 0x6d<br />#define CMD_113B 0x6e<br />#define CMD_114B 0x6f<br />#define CMD_121B 0x70<br />#define CMD_122B 0x71<br />#define CMD_123B 0x72<br />#define CMD_124B 0x73<br />#define CMD_131B 0x74<br />#define CMD_132B 0x75<br />#define CMD_133B 0x76<br />#define CMD_134B 0x77<br />#define CMD_141A 0x78<br />#define CMD_143A 0x79<br />#define CMD_144A 0x7b<br />#define CMD_211B 0x7c<br />#define CMD_212B 0x7d<br />#define CMD_213B 0x7e<br />#define CMD_221B 0x80<br />#define CMD_222B 0x81<br />#define CMD_223B 0x82<br />#define CMD_224B 0x83<br />#define CMD_232B 0x85<br />#define CMD_233B 0x86<br />#define CMD_241B 0x88<br />#define CMD_242B 0x89<br />#define CMD_A 0x8a<br />#define CMD_B 0x8b<br />#define CMD_AB 0x8c<br />#define CMD_AAA 0x8d<br />#define CMD_BBB 0x8e<br />#define CMD_BAB 0x8f<br />#define CMD_ABB 0x95<br />#define CMD_BBA 0x97<br />#define CMD_ABA 0x98<br />#define CMD_ABAB 0x99<br />#define CMD_AAAA 0x9a<br />#define CMD_FWRD 0xb7<br />#define CMD_BWRD 0xb8<br />#define CMD_FWLT 0xb9<br />#define CMD_FWRT 0xba<br />#define CMD_LEFT 0xbb<br />#define CMD_RGHT 0xbc<br />#define CMD_BKLT 0xbd<br />#define CMD_BKRT 0xbe<br />#define CMD_411A 0xc7<br />#define CMD_412A 0xc8<br />#define CMD_413A 0xc9<br />#define CMD_444B 0xca<br />#define CMD_444A 0xcb<br />#define CMD_LVSoff 0xd3<br />#define CMD_HP 0xd5<br />#define CMD_NOIMP 0xd6<br />#define CMD_END 0xd7<br />#define MSG_NOIMP 0x848080<br />#define MSG_NOIMP 0x848080<br />#define MSG_RUP 0x878280<br />#define MSG_RDW 0x808280<br />#define MSG_RRT 0x8480f0<br />#define MSG_RLT 0x848080<br />#define MSG_LUP 0x84f080<br />#define MSG_LDW 0x841080<br />#define MSG_LRT 0xec8080<br />#define MSG_LLT 0x0c8080<br /></pre><br /><br /><header:6><span style="font-size:130%;"><span style="font-family:trebuchet ms;">What NEXT?<br /></span></span><br />Now that we can sent any command it is time to try sending new code. I did try to sent CMDs 0-7 and they produce the initial iSOBOT moves (initial grittings, no input frustration, greetings etc). Also, the it would be great to explore the parameters and longer-type command.<br /><br />Command codes that I could not generate with the iSOBOT remote:<br /><pre><br />Dec Hex<br />0-6 00-06<br />11-11 0B-0B<br />13-18 0D-12<br />100-100 64-64<br />104-106 68-6A<br />122-122 7A-7A<br />127-127 7F-7F<br />144-148 90-94<br />150-150 96-96<br />155-182 9B-B6<br />191-198 BF-C6<br />204-210 CC-D2<br />212-212 D4-D4<br />216-235 D8-EB<br /></pre><br /><br />Wait for more posts about code: interrupt-based IR receiver, iSOBOT boobs-job (front backpack).<br /><br />Just exercised these "bonus" codes and got:<br /><pre><br />#define CMD_TURNON 0x01<br />#define CMD_ACTIVATED 0x02<br />#define CMD_READY 0x03<br />#define CMD_RC_CONFIRM 0x04<br />#define CMD_RC_PROMPT 0x05<br />#define CMD_MODE_PROMPT 0x06<br />#define CMD_IDLE_PROMPT 0x0B // 0x0C,0x0D,0x0E all the same<br />#define CMD_HUMMING_PROMPT 0x0F<br />#define CMD_COUGH_PROMPT 0x10<br />#define CMD_TIRED_PROMPT 0x11<br />#define CMD_SLEEP_PROMPT 0x12<br />#define CMD_FART 0x40 // 2A<br />#define CMD_SHOOT_RIGHT 0x64<br />#define CMD_SHOOT_RIGHT2 0x68<br />#define CMD_SHOOT2 0x69<br />#define CMD_BEEP 0x6a<br />#define CMD_BANZAI 0x7F<br />#define CMD_CHEER1 0x90<br />#define CMD_CHEER2 0x91<br />#define CMD_DOG 0x92<br />#define CMD_CAR 0x93<br />#define CMD_EAGLE 0x94<br />#define CMD_ROOSTER 0x95<br />#define CMD_GORILLA 0x96<br />#define CMD_LOOKOUT 0xA1<br />#define CMD_STORY1 0xA2 // knight and princess<br />#define CMD_STORY2 0xA3 // ready to start day<br />#define CMD_GREET1 0xA4 // good morning<br />#define CMD_GREET2 0xA5 // do somthing fun<br />#define CMD_POOP 0xA6 // poops his pants<br />#define CMD_GOOUT 0xA7 // ready to go out dancing<br />#define CMD_HIBUDDY 0xA8 // .. bring a round of drinks<br />#define CMD_INTRODUCTION 0xA9<br />#define CMD_ATYOURSERVICE 0xAA<br />#define CMD_SMELLS 0xAB<br />#define CMD_THATWASCLOSE 0xAC<br />#define CMD_WANNAPICEOFME 0xAD<br />#define CMD_RUNFORYOURLIFE 0xAE<br />#define CMD_TONEWTODIE 0xAF<br />// 0xB0 - nothing?<br />#define CMD_SWANLAKE 0xB1<br />#define CMD_DISCO 0xB2<br />#define CMD_MOONWALK 0xB3<br />#define CMD_REPEAT_PROMPT 0xB4<br />#define CMD_REPEAT_PROMPT2 0xB5<br />#define CMD_REPEAT_PROMPT3 0xB6<br />// 0xB7-0xC4 single steps in different directions<br />#define CMD_HEADSMASH 0xC5<br />#define CMD_HEADHIT 0xC6<br />// 0xCC-0xD2 - unknown (use param?)<br />// after exercising one of these I am getting only beeps instead of voice/sounds<br />// (looks like a tool to synchronize sound with moves)<br />#define CMD_HIBEEP 0xD3<br />// 0xD4 - unknown (use param?)<br />#define CMD_BEND_BACK 0xD8 // same untill 0xDB<br />#define CMD_SQUAT 0xDB // also 0xDC<br />#define CMD_BEND_FORWARD 0xDD<br />#define CMD_HEAD_LEFT_60 0xDE<br />#define CMD_HEAD_LEFT_45 0xDF<br />#define CMD_HEAD_LEFT_30 0xE0<br />#define CMD_HEAD_RIGHT_30 0xE1<br />#define CMD_HEAD_RIGHT_45 0xE2<br />#define CMD_HEAD_RIGHT_60 0xE3<br />// seems identical to A & B getups<br />#define CMD_GETUP_BELLY 0xE4<br />#define CMD_GETUP_BACK 0xE5<br />// E6 unknown<br />#define CMD_HEAD_SCAN_AND_BEND 0xE7<br />#define CMD_ARM_TEST 0xE8<br />#define CMD_FALL_AND_LEG_TEST 0xE9<br />#define CMD_THANKYOUSIR 0xEA<br />#define CMD_ILOVEYOU_SHORT 0xEB<br />#define CMD_3BEEPS 0xEC<br />#define CMD_FALL_DEAD 0xED<br />#define CMD_3BEEPS_AND_SLIDE 0xEE<br />// EF-FF unknown<br /></pre><br /><br /><br /></header:6></header:6>Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com2tag:blogger.com,1999:blog-1760465248680296780.post-84207222442745332582009-01-25T19:25:00.000-08:002009-01-25T20:26:53.487-08:00iRoomba battery/charger fixes, observations.<span style="font-weight: bold;">Resurection</span><br />Just picked up a used 4210 iRobot vaccum, just to check it out. It was a $30 not-working machine. The battery was a suspect so I ordered a core replacement from all-battery.com ($35). It turned out new battery did not work either. It was a charging circuit that was broken, a common failure. Thanks to the iRoomba robot enthusiasts at <a href="http://www.robotreviews.com/chat/viewtopic.php?f=1&t=3909&start=20">http://www.robotreviews.com/chat/viewtopic.php?f=1&t=3909&start=20</a><todo-link> who reverse-engineered the circuit, I was able to pinpoint the problem. I t turned out one of the power FETs (U2) was blown so I have replaced it with a bigger one (TO220 Id=18A Usd=60V) <todo-add>. Now I think I could (shoud) have replaced both U2 and U4 with this single p-Fet as it appears the only reason there are two fets in series is for the power dissipation. I will do this when U4 blows out.<br /><span style="font-weight: bold;">Motion</span><br />Now roomba does its thing but after initial exitement I am getting bored watching it obsesively cleaning the corners or areas around furniture legs, while leaving vast areas of dirt in the middle of the room untouched.<br /><span style="font-weight: bold;">Docking</span><br />Its docking algorithm is flawed. It keeps on vacuming while searching for the base and hence wasting remaining charge. It does not appears to change its motion pattern hence it keeps the corner obsession going on. This combined with a very limited range of the home base IR beacon (about 3 feet in my experience) results in almost guaranteed dead roomba lying somewhere in a corner. <br /><span style="font-weight: bold;">Navigation</span><br />..is what this robot needs. Dead reckoning could be used probably. Albeit unlike in transportation, there is no absolute North reference for heading but it is probably not needed (relative to the surrounding should be fine).. The wheel rotation sensors (both the caster and the optical pickup in drive wheels) should provide enough info assuming no slippage. This combined with bump events and memory could be sufficient for making out room/furniture layout and perhaps also provide location for the base. Best yet to equip roomba with ultrasonic range finder and have her do initial circle.<br /></todo-add></todo-link>Michal Khttp://www.blogger.com/profile/05712646808155487704noreply@blogger.com1