tag:blogger.com,1999:blog-31318664413346256912024-03-12T20:54:29.143-07:00Adventures with a Raspberry PiFootleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-3131866441334625691.post-51568136175714909872023-11-30T06:40:00.000-08:002024-02-27T07:03:27.932-08:00Pimoroni Yukon - Interfacing a Raspberry Pi to an Micro-controller running Micropython<p>I've been working on testing some new pre-release modular robotics hardware from Pimoroni. The Yukon board.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkX2FkLH_1PaYupJ122iPniMtZOyAnjLlTQsmdMLKcoREe__Cn7UURSOoA85rs3Mp79cNI96Dpa2mZN3jbO5CRrqXkKdcMoEjX6pFH5v6O1Hrls6JMNfH7Jzgm7cq6LN5YrEgSBDrUC32N7oJ_FIlUWxu5DdimdSTvtczVGweXpW0Ag-l8WpEFlBmLo6s/s4032/IMG_2904.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="4032" data-original-width="3024" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkX2FkLH_1PaYupJ122iPniMtZOyAnjLlTQsmdMLKcoREe__Cn7UURSOoA85rs3Mp79cNI96Dpa2mZN3jbO5CRrqXkKdcMoEjX6pFH5v6O1Hrls6JMNfH7Jzgm7cq6LN5YrEgSBDrUC32N7oJ_FIlUWxu5DdimdSTvtczVGweXpW0Ag-l8WpEFlBmLo6s/w480-h640/IMG_2904.jpg" width="480" /></a></div><br /><p>I am planning to build my Pi Wars robot around this, which means I need a way to talk to a Micro-python board from a Raspberry Pi. It would be really neat to be able to do this over the USB lead. This board is not a HAT, so needs powering via USB. I thought it would be great to use the USB port on the Pi to power the Yukon board, and for communication between the two.</p><p>This opened up a rabbit hole of learning. First to work out how to send data over USB serial from Python on the Pi, and how to read the data in Micropython on a connected micro-controller. I discovered that certain byte values get changed (line ending conversions) and that some kill the micro-python program (the same way pressing the 'stop' button in the Thonny IDE does). I learned how to disable this feature in micropython, and then how difficult it is to get control back when main.py auto-runs on power up and turns off the ability of the IDE to intercept and stop the program!</p><p>To avoid these problems I decided to hex encode each byte I wanted to send, so it is sent as a pair of bytes represented by ASCII characters which are safe to send. This topic raised some interest on social media, so I cleaned up the example and made it run on a vanilla Raspberry Pi Pico board. You can find the code on <a href="https://github.com/Footleg/rpi-pico/tree/main/micropython/serial_comms_over_usb" target="_blank">github.com/Footleg/rpi-pico/tree/main/micropython/serial_comms_over_usb</a></p>Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-76916631354692416602023-11-11T07:04:00.000-08:002024-02-27T07:21:11.637-08:00Developing a small robot as a code test platform<p>I have learned from previous experience in the <a href="https://piwars.org/" target="_blank">Pi Wars robotics competition</a> how important it is to get testing code early. So rather than working on the physical build of my robot, I have been working on programming robotics code around areas which are new to me. I was already developing a small robot for STEM outreach events, based around the <a href="https://shop.pimoroni.com/products/inventor-hat-mini" target="_blank">Inventor HAT mini</a> board from Pimoroni.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikvGG4dGVj-ZhRDIjHGWR-DhgwHa8ch0nmyawzjWBn1mZD1bmZksuvznfEGns4uGOj6X0KQ0e5xlQi3JhNb3ziPS9RzZlnBQmLIK4ATf_VhT8M254Hojr3vsVtVMSy-AZXYvrMMslsF0w5qWqM0OOzfjEhqOmdNClFiGIeCq0UH-K6oV-VCem3cNv-WIg/s2973/IMG_2981.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2400" data-original-width="2973" height="323" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikvGG4dGVj-ZhRDIjHGWR-DhgwHa8ch0nmyawzjWBn1mZD1bmZksuvznfEGns4uGOj6X0KQ0e5xlQi3JhNb3ziPS9RzZlnBQmLIK4ATf_VhT8M254Hojr3vsVtVMSy-AZXYvrMMslsF0w5qWqM0OOzfjEhqOmdNClFiGIeCq0UH-K6oV-VCem3cNv-WIg/w400-h323/IMG_2981.jpg" width="400" /></a></div><p>This board supports encoder motors, something I have not developed code for previously. I wanted more feedback from my robot to better control it autonomously. Encoders enable you to read the speed of rotation of your motors, and count how many rotations they have made. This makes speed control possible, and distance travelled to be tracked. All my previous robots have been manual control only, so this was all new for me. I also added and IMU, which would enable measuring the orientation of the robot. This makes accurate turns possible.</p><p>The triangular tracked robot I was already developing is a little too small for Pi Wars, but the code developed on it should be portable to my competition robot once I have that built. I wrote a hardware abstraction interface so that my code talks to an interface which is independent of the specific hardware it is running on. I converted my manual control robot program from my STEM event robots to use the interface, creating this <a href="https://github.com/Footleg/universal-robot" target="_blank">Universal Robot project</a> on Github.</p>Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-63725416871360943042023-09-30T04:49:00.000-07:002024-01-30T05:02:08.742-08:00Pi Wars 2024 - The Beginning<p>Hard to believe it is almost 5 years since my last Pi Wars blog entry. Since I last entered as a competitor in 2019, I have mentored school teams each year the competition has run, and so decided not to enter myself after discovering just how much work that was in 2019! This year my plans to run another after school robotics club fell through when the Computer Science teacher I worked with last time left the school. So I thought I should enter again myself. I've built quite a few robots over the years since my last time, so I've been promoted to the 'veterans' category this time around. I just need a name and an idea now!</p><p>With the entry deadline fast approaching, I decided the most visually exciting robot I could think of would use 4 RC tracks in the place of wheels on a 4 'wheeled' rocker-bogie suspension. I've had these tracks in the parts box for a while, intending to build a robot out of them.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5X_xppd7m_yZlwFp3nQq8TSit7whSxbHpqxStYcij-cttcSITBdtbxzwFcdmd0etzEsa9asQvpb0Wx4D57nhI3CVfmYHdGVcXhdr1jkIjxhJ1-0dRXE1YOIavjFVf8HMj4GYT-LnNS4WZliHPHTMeJ5gTV2wDOwBZEromkk3NZMMIddkfJlomyqytVcU/s4032/IMG_2853%20(1).jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5X_xppd7m_yZlwFp3nQq8TSit7whSxbHpqxStYcij-cttcSITBdtbxzwFcdmd0etzEsa9asQvpb0Wx4D57nhI3CVfmYHdGVcXhdr1jkIjxhJ1-0dRXE1YOIavjFVf8HMj4GYT-LnNS4WZliHPHTMeJ5gTV2wDOwBZEromkk3NZMMIddkfJlomyqytVcU/w400-h300/IMG_2853%20(1).jpg" width="400" /></a></div><br /><p>So that's the idea. In keeping with the theme 'Disaster Zone', I needed a robot name. So I decided on:</p><span style="background-color: white; color: #222222; font-family: Arial, Helvetica, sans-serif;"><b>Team name: </b>Footleg </span><span class="il" style="background-color: white; color: #222222; font-family: Arial, Helvetica, sans-serif;">Robotics</span><br style="background-color: white; color: #222222; font-family: Arial, Helvetica, sans-serif;" /><p><span class="il" style="background-color: white; color: #222222; font-family: Arial, Helvetica, sans-serif; font-weight: bold;">Robot</span><span style="background-color: white; color: #222222; font-family: Arial, Helvetica, sans-serif;"><b> name: </b>Ragnarök </span><span class="il" style="background-color: white; color: #222222; font-family: Arial, Helvetica, sans-serif;">Rescue</span></p><p><span class="il" style="background-color: white; color: #222222; font-family: Arial, Helvetica, sans-serif;"><br /></span></p><p>Just as I had decided to enter, my daughter told me she was going to enter as a young person team with a school friend, and wanted me to be their team mentor. So here I am again, entering myself, and mentoring a young persons team at the same time. Will I never learn?</p>Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-25845130628564761382021-08-28T08:33:00.000-07:002021-08-28T08:34:59.814-07:00Running Robot Code on Start-up with systemd<p>Following the excellent <a href="https://blog.usedbytes.com/2019/11/run-at-startup-without-rc.local/" target="_blank">blog post</a> by Brian Starkey @usedbytes to set up my robot programs to launch on start-up on a Raspberry Pi, I found several things which didn't work with my particular programs. This article aims to extend the information from Brian's post.</p><p>First a quick recap on why use systemd services instead of rc.local or autostart desktop files. For me the main advantages of this method are:</p><p></p><ul style="text-align: left;"><li>The automatic start up of the robot code on boot can be turned on and off, which really helps when developing code and you don't want the robot program to launch each time you boot up.</li><li>You can configure the code to be restarted if it stops for any reason. Great for if an unexpected bug crashes your robot code in the middle of a demo or competition. No need to wait for a reboot to get the code running again.</li></ul><div>So what went wrong when I tried to implement the services as described in Brian's blog? First I want to point out that nothing in Brian's blog was wrong. I just needed some additional configuration for my programs. The first problem I ran into was that I had only installed the python packages my program needed as the pi user, but found that the service was running as root. This can be fixed by installing all the packages as root, but I found an alternative option. You can specify the user to run the service as by putting User=pi in the service definition file.</div><div><br /></div><div>The second problem I ran into was that my service ran in a headless mode, even though my Raspberry Pi was running a full desktop OS. This works fine for a python program which does not use the display, but my robot programs are usually built on top of pygame and use this to display information and sometimes control menus in a GUI. Running my programs as a service caused pygame to exit with '<span style="font-family: courier;">pygame.error: Unable to open a console terminal</span>'. So I had to learn how to run a service with access to the display device. This required a couple of lines to be added to the [Service] section:</div><p></p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><div><span style="font-family: courier;">Environment="DISPLAY=:0"</span></div><div><div><span style="font-family: courier;">Environment="XAUTHORITY=/home/pi/.Xauthority"</span></div></div></blockquote><div><div></div></div><p></p><div>I also needed to change the [Install] section WantedBy value:</div><p></p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><span style="font-family: courier;">[Install]</span><br /><div><span style="font-family: courier;">WantedBy=graphical.target</span></div></blockquote><p> </p><div style="text-align: left;">I am not going to repeat all the information from Brian's blog article here. You should read that first if you are not familiar with how to set up and configure services to run on boot. Once I had everything working this is what my runrobot.service file looked like.</div><div style="text-align: left;"><br /></div><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><div></div><div><div><span style="font-family: courier;">[Unit]</span></div><div><span style="font-family: courier;">Description=Robot Runner</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">[Service]</span></div><div><span style="font-family: courier;">Type=exec</span></div><div><span style="font-family: courier;">ExecStart=/usr/bin/python3 /home/pi/pygame-controller/examples/SentinelBoard/Turbo4WD.py</span></div><div><span style="font-family: courier;">User=pi</span></div><div><span style="font-family: courier;">Environment="DISPLAY=:0"</span></div><div><span style="font-family: courier;">Environment="XAUTHORITY=/home/pi/.Xauthority"</span></div><div><span style="font-family: courier;">Restart=always</span></div><div><span style="font-family: courier;">RestartSec=5s</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">[Install]</span></div><div><span style="font-family: courier;">WantedBy=graphical.target</span></div></div></blockquote><div><br /></div><h3 style="text-align: left;">Command Quick Reference</h3><div>The service file needs to be copied into /etc/systemd/system in order to work:</div><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px;"><span style="font-family: courier;">sudo cp runrobot.service /etc/systemd/system</span></blockquote><div><br /></div><div>As long as the filename ends '.service' you do not need to specify the full filename in all the commands. You can just use the service name (runrobot in this case).</div><div><br /></div><div><div>If you change the .service file then the changes will not be picked up until the next reboot, or after you run this command:</div><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px;"><span style="font-family: courier;">sudo systemctl daemon-reload</span></blockquote><div><br /></div></div><div>To enable service (make it run on boot):</div><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><div style="text-align: left;"><span style="font-family: courier;">sudo systemctl enable runrobot</span></div></blockquote><div><br /></div><div>Disable service (stop it running on boot):</div><div><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px;"><span style="font-family: courier;">sudo systemctl disable runrobot</span></blockquote><div><br /></div></div><div><div>Start service (run the robot program without doing a reboot):</div><div><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px;"><span style="font-family: courier;">sudo systemctl start runrobot</span></blockquote><div><br /></div></div></div><div><div>Stop service (stop it running):</div><div><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px;"><span style="font-family: courier;">sudo systemctl stop runrobot</span></blockquote><div><br /></div></div></div><div><div>View output from the service/program since last boot:</div><div><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px;"><span style="font-family: courier;">sudo journalctl -b0 --unit=runrobot</span></blockquote><div><br /></div></div></div><div><br /></div>Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-63375729925873971622021-06-29T02:14:00.001-07:002021-06-29T02:14:31.980-07:00Dr Footleg on YouTube<p>My video content can be found at <a href="https://www.youtube.com/channel/UC4vql6TvPB2qHxeghnWC9IQ">Dr Footleg on YouTube</a> for my own channel. For much of my content recorded for other organisations I post links to it all on my <a href="https://ko-fi.com/footleg" target="_blank">Ko-Fi page</a> so this is the place to find my talks on home robotics and PCB design.</p>Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-62842906543187151672020-09-23T11:10:00.003-07:002020-09-26T11:01:17.259-07:00Arduino Development using VSCode<p>The Arduino IDE provides a means to write code for microcontrollers, with library management, compilation and uploading of your code. But the code development environment is lacking many of the features of a modern IDE. Enter VSCode to the rescue! Providing syntax checking, auto-indentation (with clean up), and code completion via the IntelliSense feature. VSCode is free and provides a capable development environment which supports multiple languages, remote code development over SSH and many other capabilities via a comprehensive library of extensions. In this article, we will be looking at options to use it to develop code for Arduino (and Arduino supported boards).</p><p>Before starting with VSCode, you need to install the Arduino Desktop IDE (at time of writing this was v1.8.13). You can download it from <a href="https://www.arduino.cc/en/main/software" rel="nofollow" target="_blank">www.arduino.cc/en/main/software</a>. The VSCode extensions use the Arduino IDE under the hood, so you need this to be working with your boards. Check that example sketches can be compiled and deployed onto your board using the Arduino IDE. </p><p>Now we can set up VSCode. You can download the editor from <a href="https://code.visualstudio.com/" rel="nofollow" target="_blank">code.visualstudio.com/</a></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3luNT7mwEQRQ1uG5z8wOWpNQyMyaMhJPxx58GE8TYepa_8gI7RMc8k6-J8e7BSlPzx-SvKzc5aXhE_PnmwdUNpQHRRS9eBCPWWzYGjo4O4A92IC-eOEGpM-kJCO4MoguBohS3EE_OKEU/s641/VSCodeWelcome.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="510" data-original-width="641" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3luNT7mwEQRQ1uG5z8wOWpNQyMyaMhJPxx58GE8TYepa_8gI7RMc8k6-J8e7BSlPzx-SvKzc5aXhE_PnmwdUNpQHRRS9eBCPWWzYGjo4O4A92IC-eOEGpM-kJCO4MoguBohS3EE_OKEU/s16000/VSCodeWelcome.png" /></a></div><br /><p>We will be writing C/C++ code for Arduino, so we need to install the extension to add support for this language. </p><p>Down the lefthand side of the VSCode window is a vertical toolbar. Click on the Extensions button to open the extensions manager. </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihMTOGrVUfh-5ki21IlCqsltHrz954czNvyCkMsijWUHadNfHUBl51BBucfgvLaZ0uPTyWCAqgQaAuLtEFC-HInXBFuJ_BSNN_M-G5h0Rk2T8e2A5IESh7MVtWGEdOBXOfkKo2LgDWElM/s48/VSCodeExtnsBtn.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="48" data-original-width="48" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihMTOGrVUfh-5ki21IlCqsltHrz954czNvyCkMsijWUHadNfHUBl51BBucfgvLaZ0uPTyWCAqgQaAuLtEFC-HInXBFuJ_BSNN_M-G5h0Rk2T8e2A5IESh7MVtWGEdOBXOfkKo2LgDWElM/s0/VSCodeExtnsBtn.png" /></a></div><br /><p></p><p><br /></p><p>Find and install the C/C++ extension:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJH69no1UpF0Rd4Hz0T-xI_foK4lBgwIMBqyPkNGgfej5_7JIkw3UuI6Bs3r1gxi1NN-X0Q12XIJWGHl9RDjdi9U1TIthd4BYumfwyWylktJUi_NKZhKciRPKZK5922aHGPxdOUG4E3o8/s891/VSCodeCppExtn.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="659" data-original-width="891" height="474" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJH69no1UpF0Rd4Hz0T-xI_foK4lBgwIMBqyPkNGgfej5_7JIkw3UuI6Bs3r1gxi1NN-X0Q12XIJWGHl9RDjdi9U1TIthd4BYumfwyWylktJUi_NKZhKciRPKZK5922aHGPxdOUG4E3o8/w640-h474/VSCodeCppExtn.png" width="640" /></a></div><br /><p>There are two options to add support for Arduino development. The more obvious looking one is the Arduino extension. I was able to get this working with some configuration required, but a number of features did not work for me. I could not open the Serial Monitor, Teensy boards were not supported and I found the IntelliSense feature reported problems in my code which were not problems for the Arduino compiler. I did learn a few tricks to make things workable and I have detailed these at the end of this article if you want to use this extension. But I found things worked better for me using the alternative option, the PlatformIO IDE extension. You probably don't want to install both as the IntelliSense feature configurations of each are not compatible.</p><h2 style="text-align: left;">PlatformIO IDE</h2><p>The PlatformIO IDE extension provides support for more boards (including the Teensy family), but it is not as tolerant of the non-standard C/C++ syntax which Arduino sketches allow. You will need to convert any .ino files into .cpp files in your projects to work with this extension. You will also find that functions have to be declared before they are used, and global variables and functions declared in one file in a project will not be in scope in other files. More details on this later, but aside from these code compatibility issues I found it very easy to set up and most of the configuration was automatic.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsuNPwe5Q6cQ0NBj9uNX2OvST-Mgdh7YEJDrS9TF411OAV0FpWMS4qY6lQyen_E5X7MV6emNbP6nQfntmZRAN3TzqamP2VCUxEVKnuS2KfS4n95RlqBW3NiToW3CJ4y86yUDeaULkpDEc/s891/VSCodePlatformIOExtn.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="659" data-original-width="891" height="474" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsuNPwe5Q6cQ0NBj9uNX2OvST-Mgdh7YEJDrS9TF411OAV0FpWMS4qY6lQyen_E5X7MV6emNbP6nQfntmZRAN3TzqamP2VCUxEVKnuS2KfS4n95RlqBW3NiToW3CJ4y86yUDeaULkpDEc/w640-h474/VSCodePlatformIOExtn.png" width="640" /></a></div><br /><p>To get started with the PlatformIO IDE, I suggest you follow their quickstart guide. That is what I did, and there is little point in me repeating that information here. See <a href="https://docs.platformio.org/en/latest/integration/ide/vscode.html#quick-start">https://docs.platformio.org/en/latest/integration/ide/vscode.html#quick-start</a> </p><p>Once I had built a basic blink sketch following the quickstart guide, I successfully imported an existing Arduino project from the extension home page, ticking the option to use the Arduino libraries already installed on my computer. This created a copy of the project under my <user>/Documents/PlatformIO/Projects directory, with the configuration set up to include libraries from the existing Arduino IDE installation on my computer. You select the board you want to compile for in the import dialog. I already had the Teensyduino packages installed, and found the Teensy boards listed in the board picker. The IDE warned me that I should change the .ino file to a .cpp file in order for IntelliSense to work. The project source was also put under a 'src' folder. Projects with both cpp and header files should be reorganised by moving the h files from the src folder into the include folder. I just renamed my single ino file through the VSCode explorer pane and I was able to compile and upload the project to my Teensy 3.2 board.</p><p>One additional configuration change I made was in the platformio.ini file under my project. I added a build_cache_dir line as follows in my ini file. You can point this to any folder you like outside your project. By doing this, libraries compiled as part of your sketch will not need recompiling every time you rebuild. So after the first build, subsequent builds will only need to recompile classes with code changes, which will be faster.</p><div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div>[platformio]</div><div><span style="color: #6a9955;">; Set a path to a cache folder</span></div><div><span style="color: #569cd6;">build_cache_dir</span> = C:/temp/PlatformIO_buildcache</div><br /></div><p>You can also add additional library paths in this file. I was working on a project which uses a library I am also developing on my computer. So I added a path to my library code in development after the path to the Arduino libraries (note the syntax ~ to refer to your user home directory):</p><div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div>[env:teensy31]</div><div><span style="color: #569cd6;">platform</span> = teensy</div><div><span style="color: #569cd6;">board</span> = teensy31</div><div><span style="color: #569cd6;">framework</span> = arduino</div><div><span style="color: #569cd6;">lib_extra_dirs</span> = </div><div> ~/Documents/Arduino/libraries</div><div> ~/Documents/dev/Cpp/RGBMatrixAnimations</div></div><p>That was all I needed to do to get up and running with simple single file sketches. But to make multi-file projects compatible I needed to make some code changes. The Arduino IDE does some rewriting of your code before it compiles it. All .ino files in the project are essentially combined into one large code file, and any functions defined in them have declarations added to the code before they get called. You do not get any of this in PlatformIO. This does force you to write more standards compliant code though, so it is no bad thing. To get my more complex project to compile I had to do the following:</p><p></p><ol style="text-align: left;"><li>All .ino files in a project need to be changed to the extension .cpp</li><li>Functions defined in my main cpp file needed to either be defined before they are called, or have forward declarations added near the top of the file. (This article explains it in more detail: <a href="https://community.platformio.org/t/order-of-function-declaration/4546/2">https://community.platformio.org/t/order-of-function-declaration/4546/2</a> ).</li><li>To call any code in other .cpp files requires an include for that .cpp file adding to the file calling that code. This also means you need to add includes for any library header files to all the cpp files which use those libraries (rather than just once in the main project code file).</li><li>Global variables declared in the main code file can no longer be accessed from code in other files. So you'll need to pass them to the code using them in other files (either via class constructors or as parameters to any methods).</li></ol><div>I avoided declaring functions directly in secondary cpp files, instead using these files only for class declarations. You can then pass variables to these classes via their constructors, or setter member methods. This gives tighter scope control and makes for more robust code. Overall I found the PlatformIO extension worked better for me than the Arduino extension, but if you want a more Arduino like coding experience rather than standards compliant C++ then you may find the Arduino extension suits you better.</div><p></p><h2 style="text-align: left;">Arduino Extension</h2><p>If you want to use the Arduino extension instead of PlatformIO (maybe you want to work on projects with .ino files for example), then install that extension instead.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWJF9twNgwHP39c-a3y4ZZwdJ3I1wwFcjt3BYQ8UKkm2Wg4f_voSMCY6ANPW7VELQfDYYWRt8mQakNdfuKFSAPrTvA4og7kIeq0guLzZ2b21v5OjBT9YbIgNdvqIX8-deJORFQ4j4ASIs/s891/VSCodeArduinoExtn.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="659" data-original-width="891" height="474" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWJF9twNgwHP39c-a3y4ZZwdJ3I1wwFcjt3BYQ8UKkm2Wg4f_voSMCY6ANPW7VELQfDYYWRt8mQakNdfuKFSAPrTvA4og7kIeq0guLzZ2b21v5OjBT9YbIgNdvqIX8-deJORFQ4j4ASIs/w640-h474/VSCodeArduinoExtn.png" width="640" /></a></div><br /><p>This adds several Arduino commands to the command palette. With this installed, when you open an Arduino sketch (.ino) file in VSCode you should see a custom footer bar with clickable options to select the connected board, COM port and Programmer (if you are using one). Click on the <select board> item and the board manager should open (you can also open it via the Command Palette). I found the <select PORT> command was not working, so I had to set it manually in the arduino.json file. Open this file from the .vscode folder in your workspace, and add the COM port line as follows (setting the correct numbered COM port matching the one you used to program your board from the Arduino IDE).</p><div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><span style="color: #9cdcfe;">"port"</span>: <span style="color: #ce9178;">"COM4"</span>,</div><p>You should now be able to verify sketches and upload them to your board using the Arduino commands.</p><p>Open Command Palette (Ctrl + Shift + P), and type 'Arduino' to filter the commands list in the command picker. You will see 'Arduino: Verify' and 'Arduino: Upload' commands. Note these also have keyboard shortcuts displayed. e.g. You can compile and Upload the open sketch using Ctrl + Alt + U.</p><p>The first time you do this for a project, you will be asked which .ino file is the main one (if you have more than one in the sketch). Once you select this it is added into the arduino.json configuration file (so you know where to go to change it if you change the main file later).</p><p>You may see a warning at the start of the compiler output, saying 'Output path is not specified. Unable to reuse previously compiled files. Upload could be slow. See README.'. This means that each time you make a code change and go to upload again, the compiler has the recompile the entire project including all libraries, which can take a long time. To allow it to reuse the output from a previous compile and only recompile the files which have been changed, you need to define and output folder in the arduino.json file. This folder should not be under the project folder. You can add the following line to set the output to a folder named ArduinoOutput located alongside your project. Alternatively give a full path to a folder, maybe in your temp directory.</p><div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div> <span style="color: #9cdcfe;">"output"</span>: <span style="color: #ce9178;">"../ArduinoOutput"</span>,</div><div></div></div><p>This should get you to the point where you can open, edit, compile and upload sketches to your boards. But you may notice the code IDE still shows lots of errors in the code because the VSCode IntelliSense feature does not know where all the Arduino libraries are located. We need to add these to the workspace include paths:</p><p>Using the command palette, run the command: C/C++: Edit Configurations (UI)</p><p>This will open the UI to edit your C/C++ configuration. You can edit your win32 configuration, or create a new one. I decided to create a new one named 'arduino'.</p><p>In the 'Include Path' field, make sure all 3 of these paths are added in addition to the workspaceFolder item:</p><div style="text-align: left;"><span style="font-family: courier;">${env:userprofile}/AppData/Local/Arduino15/packages/**<br /></span><span style="font-family: courier;">${env:userprofile}/Documents/Arduino/libraries/**<br /></span><span style="font-family: courier;">C:/Program Files (x86)/Arduino/hardware/arduino/avr/libraries/**</span></div><div><p>That last one assumes you installed the Arduino IDE into the default location under <span style="font-family: courier; font-size: small;">C:\Program Files (x86)\Arduino. </span>If you installed to a different location then change it as appropriate. Note the use of the userprofile environment variable to make the configuration work on any computer. These configuration files can be checked into source control so that your projects can be checked out and run quickly on different computers regardless of the logged in username.</p><p><br /></p><p>My complete arduino configuration section looked like this:</p><div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div> {</div><div> <span style="color: #9cdcfe;">"name"</span>: <span style="color: #ce9178;">"arduino"</span>,</div><div> <span style="color: #9cdcfe;">"includePath"</span>: [</div><div> <span style="color: #ce9178;">"${workspaceFolder}/**"</span>,</div><div> <span style="color: #ce9178;">"${env:userprofile}/AppData/Local/Arduino15/packages/**"</span>,</div><div> <span style="color: #ce9178;">"${env:userprofile}/Documents/Arduino/libraries/**"</span>,</div><div> <span style="color: #ce9178;">"C:/Program Files (x86)/Arduino/hardware/arduino/avr/libraries/**"</span></div><div> ],</div><div> <span style="color: #9cdcfe;">"defines"</span>: [</div><div> <span style="color: #ce9178;">"_DEBUG"</span>,</div><div> <span style="color: #ce9178;">"UNICODE"</span>,</div><div> <span style="color: #ce9178;">"_UNICODE"</span></div><div> ],</div><div> <span style="color: #9cdcfe;">"compilerPath"</span>: <span style="color: #ce9178;">"C:</span><span style="color: #d7ba7d;">\\</span><span style="color: #ce9178;">Program Files (x86)</span><span style="color: #d7ba7d;">\\</span><span style="color: #ce9178;">mingw-w64</span><span style="color: #d7ba7d;">\\</span><span style="color: #ce9178;">i686-8.1.0-posix-dwarf-rt_v6-rev0</span><span style="color: #d7ba7d;">\\</span><span style="color: #ce9178;">mingw32</span><span style="color: #d7ba7d;">\\</span><span style="color: #ce9178;">bin</span><span style="color: #d7ba7d;">\\</span><span style="color: #ce9178;">gcc.exe"</span>,</div><div> <span style="color: #9cdcfe;">"cStandard"</span>: <span style="color: #ce9178;">"gnu18"</span>,</div><div> <span style="color: #9cdcfe;">"cppStandard"</span>: <span style="color: #ce9178;">"gnu++14"</span>,</div><div> <span style="color: #9cdcfe;">"intelliSenseMode"</span>: <span style="color: #ce9178;">"gcc-x64"</span></div><div> }</div><div></div></div><p>Finally, open the command palette again and run the command <span style="font-family: courier;">C/C++: Select a configuration</span>, and select the 'arduino' configuration. This should clear most of the reported 'problems' in the code IDE, and IntelliSense code completion suggestions should now be working. There are some exceptions to this however.</p><p>The Arduino IDE appears to treat all .ino files in a project directory as being part of the main .ino file. So any code split across different .ino files will be compiled by the Arduino IDE as if that code was all in one big file. However the VSCode IntelliSense environment does not do this. One way to avoid this problem is to only have a single .ino file in your project, and use the extension .cpp for any other code files. You will then have to add #include statements as required to include these .cpp files in other files which reference them, and you will no longer be able to access globals defined in the main .ino file from code in the .cpp files. It will make you write better code, forcing references to be passed to objects rather than being accessible everywhere via globals. But you may find projects published by others do not work with the IntelliSense feature in VSCode.</p><p>In some cases, libraries will have been written to be compatible with both Arduino and Windows/Linux C/C++ programs. These can cause problems because the VSCode IntelliSense environment does not realise it is running in an Arduino environment. So it tries to check the code against windows libraries which will not be on your Arduino project path. You can make it behave like an Arduino environment by adding the following line to the start of your main sketch .ino file:</p><p><span style="font-family: courier; font-size: x-small;">#define ARDUINO 100</span></p><p>But I suggest commenting out the line before compiling as the Arduino IDE will set it's own define, which may be different to this. Better to just live with these reported include errors since they will not apply when the Arduino IDE compiles the code.</p><p>Some data types in my project were flagged as not defined by default in standard C/C++. These included:</p><p></p><ul style="text-align: left;"><li>byte</li><li>boolean</li><li>uint8_t/uint16_t/uint_32_t</li></ul><div>If you want to avoid these being flagged as errors by IntelliSense then you can use bool in place of boolean, uint8_t in place of byte. Then to make IntelliSense aware of the uint types, I added the following #if defines which I use in code designed to be compatible with both Arduino and non-Arduino environments:</div><div></div><p></p><div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div><span style="color: #c586c0;">#if</span><span style="color: #569cd6;"> </span><span style="color: #c586c0;">defined</span><span style="color: #569cd6;">(ARDUINO) </span>&&<span style="color: #569cd6;"> ARDUINO </span>>=<span style="color: #569cd6;"> </span><span style="color: #b5cea8;">100</span></div><div><span style="color: #c586c0;">#include</span><span style="color: #569cd6;"> </span><span style="color: #ce9178;">"Arduino.h"</span></div><div><span style="color: #c586c0;">#elif</span> <span style="color: #dcdcaa;">defined</span>(ARDUINO)</div><div><span style="color: #c586c0;">#include</span><span style="color: #569cd6;"> </span><span style="color: #ce9178;">"WProgram.h"</span></div><div><span style="color: #c586c0;">#else</span></div><div><span style="color: #c586c0;">#include</span><span style="color: #569cd6;"> </span><span style="color: #ce9178;"><stdint.h></span></div><div><span style="color: #c586c0;">#include</span><span style="color: #569cd6;"> </span><span style="color: #ce9178;"><stdio.h></span></div><div><span style="color: #c586c0;">#endif</span></div></div></div><div><br /></div><div>I am not sure how much of this was really needed, as the IntelliSense appeared somewhat temperamental about which errors it reported. Sometimes if would just be complaining that included libraries referenced header files it could not find, but then it would suddenly report most of my file contained errors.</div><div><br /></div><div>I was unable to get the serial monitor working under the Arduino extension. When I clicked the icon in the footer toolbar to open it, I saw the following error: <span face=""Segoe WPC", "Segoe UI", sans-serif" style="background-color: #062f4a; color: #cccccc; font-size: 13px;">.vscode\extensions\vsciot-vscode.vscode-arduino-0.3.2\out\node_modules\usb-detection\build\Release\detection.node is not a valid Win32 application.</span></div><div><br /></div><div>I uninstalled the Arduino extension after I discovered the PlatformIO IDE extension, which appears to be working much better for me. If you have more success then please share in the comments.</div>Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-15490906203095912962019-03-14T05:46:00.001-07:002019-03-14T06:30:19.917-07:00A Complete Rebuild in AcrylicIt was always my plan to make my competition robot in transparent laser cut acrylic, so that the insides could be seen. Plus it just looks so nice! Having learned the art of designing and building a laser cut robot using 3 mm plywood I was now ready to re-cut the refined design in acrylic. The main modification I made was to shorten the legs by 15 mm. I had realised from driving my prototype that it really did not need such high ground clearance as the small wheels could not climb over anything but small obstacles. It was also a little unstable. I could get it to lift some of the wheels off the ground doing sharp turns at speed!<br />
<br />
I added some engraving to various parts and also added holes for threading all the motor and servo wires through the legs. I had drilled these holes by hand on the wooden model. Now I knew where I wanted them I added them to the CAD model so these could be laser cut on the acrylic parts. I had already designed an acrylic mount for my main display and had this mounted on the wooden chassis.<br />
<br />
With so many parts to cut I wanted to make optimum use of my acrylic sheet material. So I used an online SVG nesting tool to layout the parts. I prepared an SVG file of all the parts in Inkscape, including a containing rectangle required by the nesting tool to limit the area and shape to fit the parts into. I uploaded this to <a href="https://svgnest.com/">https://svgnest.com/</a> which generated a cutting layout for me to download.<br />
<br />
<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/AVvXsEic32OSZj3_emvXR2_Yi_ifwUUt0qFhf5dvxvZs76ne2ySff9UUpDS7hhO99C2sTWJnjKb3rqBlwTySIjnznHmWP_oHsxE7FZTAZQUL1LIatnPzTRKmXMv8cDorBNazokrxhTzYteXKhmQ/s1600/Nested+Parts.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="776" data-original-width="778" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic32OSZj3_emvXR2_Yi_ifwUUt0qFhf5dvxvZs76ne2ySff9UUpDS7hhO99C2sTWJnjKb3rqBlwTySIjnznHmWP_oHsxE7FZTAZQUL1LIatnPzTRKmXMv8cDorBNazokrxhTzYteXKhmQ/s400/Nested+Parts.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">An optimised parts layout for laser cutting</td></tr>
</tbody></table>
<br />
<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/AVvXsEiqXdWIbeeAatJPs4MMePpWYZjnEt52d2HaTEaZyVXHkUVtGf0g7nIMjHFKdanoKGe-LeyVB5lA4IL5nY1UjlHl7EnW2eBmofhz7yWgbrUpxUvi0wg5IDvYFoFMrNKyuswm4q991WvUdZY/s1600/IMG_2641.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1139" data-original-width="1600" height="454" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqXdWIbeeAatJPs4MMePpWYZjnEt52d2HaTEaZyVXHkUVtGf0g7nIMjHFKdanoKGe-LeyVB5lA4IL5nY1UjlHl7EnW2eBmofhz7yWgbrUpxUvi0wg5IDvYFoFMrNKyuswm4q991WvUdZY/s640/IMG_2641.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The complete set of laser cut acrylic parts ready to assemble</td></tr>
</tbody></table>
<br />
First I assembled the 4 steering legs. One snag I ran into is the inconsistency in thickness of acrylic sheets. A 3 mm sheet can vary in thickness between around 2.8 mm and 3.2 mm. This is due to the surface tension on the sheet when it is being cast, which results in a curved top surface dipping down towards the middle of the sheet. The sheet sizes you typically buy are cut from this larger cast sheet. Depending on which part of the cast sheet your piece was cut from you get different thicknesses across your piece. Some of my sheets exceeded 3 mm thickness towards one end, so some of my parts did not slot together as all my slots are cut at 3 mm wide. I had to re-cut a few parts with slightly wider slots. But I did not want to make all my slots wider by default, particularly the motor mounting plates which wobbled too much when the slots were not a tight fit. This an area which could do with some more refinement so that the rigidity of the motor mounts is not so dependent on tight tolerances. In the process of assembly I accidentally snapped one part in half and cracked another by over tightening the bolts holding the parts together. Acrylic is a much more brittle material than plywood and is easy to crack, especially around rectangular holes with sharp internal corners. I later modified some of my parts to increase the width of material around the outside edges of the slots from 3 mm to 4 mm to increase the strength of some parts. After re-cutting (plus a few spares) I had two completed Rocker Bogie arms.<br />
<br />
<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/AVvXsEhPeWDLLrm3StqGCPukkyoYYxHigb1JHaviEIjhMnFfNg_TKpALKN3AOydPExG8HIzRqcsPEYYndioCOWdRzQBaBI3Yg4LkiWdnxZrxqCecjPGDydXxiodqF7EO2BRkUiT8oAj7Q7x3Ag0/s1600/IMG_2801.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1389" data-original-width="1600" height="554" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPeWDLLrm3StqGCPukkyoYYxHigb1JHaviEIjhMnFfNg_TKpALKN3AOydPExG8HIzRqcsPEYYndioCOWdRzQBaBI3Yg4LkiWdnxZrxqCecjPGDydXxiodqF7EO2BRkUiT8oAj7Q7x3Ag0/s640/IMG_2801.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The Rocker Bogie arms remade in acrylic with cable routing holes</td></tr>
</tbody></table>
<br />
As I assembled my robot using the new parts, I tried to extensively photo-document every step of the process. My plan is to write up a full build guide and possibly release a kit of parts for others to build their own rover from my design.<br />
<br />
<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/AVvXsEh8T8IegpfAYc07s-ZyosP-19vHRJBiA_8Jo9RUtP_FBkEdqeWhMjglrLhf1lvpi_PBh3pQ5hHV88D7sdt8cxmbYL8RiknWcPZCYu35MHUdcxIbbLdRxE1IILMjuTI1VH0bTqraTIhwa-g/s1600/BuildPhotosThumbnails.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1600" data-original-width="1498" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8T8IegpfAYc07s-ZyosP-19vHRJBiA_8Jo9RUtP_FBkEdqeWhMjglrLhf1lvpi_PBh3pQ5hHV88D7sdt8cxmbYL8RiknWcPZCYu35MHUdcxIbbLdRxE1IILMjuTI1VH0bTqraTIhwa-g/s640/BuildPhotosThumbnails.jpg" width="598" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Some of the many photographs I took to document the assembly process</td></tr>
</tbody></table>
<br />
Another problem which came from switching to acrylic was that the plates did not grip each other like the plywood had. Some of my chassis body side plates were not staying together at the ends furthest from the bolts holding them in place. I had to add some additional T-slots and bolts to hold everything firmly together. I had designed a new front plate to mount a Pixy2 camera on, and this was not held on with anything more than the friction of the tabs in the slots. This would need more refinement for the competition as it was also going to be holding my Pi Noon attachment and I did not want that falling off mid-battle. For for now I could push it on and it looked good enough for me to shoot some photos. I set up my filming lights to provide some nice back lighting and took a few photos to try and capture the beauty of the acrylic design.<br />
<br />
<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/AVvXsEg2GRo2g_hd-vBLBvqtnzZME0eFoTS3abNyDYpVgFPCSnQtNsQ_M1zag9M641lEVd1roMTqx0x5ku8JA5lUIuwI0y2LsH4aZSQuifmfg7MdBgryBWJ2LZOt-XjAwx91s_ZsHlFjBwZw1z0/s1600/Program+Photo.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1236" data-original-width="1600" height="494" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2GRo2g_hd-vBLBvqtnzZME0eFoTS3abNyDYpVgFPCSnQtNsQ_M1zag9M641lEVd1roMTqx0x5ku8JA5lUIuwI0y2LsH4aZSQuifmfg7MdBgryBWJ2LZOt-XjAwx91s_ZsHlFjBwZw1z0/s640/Program+Photo.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">My final photo submitted for the Pi Wars 2019 program</td></tr>
</tbody></table>
<br />Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-65664174045176833392019-03-13T10:19:00.000-07:002019-03-13T10:19:03.728-07:00Another Redesign: Electronics CartridgeOne problem I identified with my robot chassis design was that I could not access any of the electronics without taking the whole thing apart. It was not possible to remove the SD Card from the Raspberry Pi without unscrewing the Pi either. One option for the SD Card access which Brian Corteil suggested was to boot the Pi from a USB thumb drive instead. I had not realised this was possible, but some testing with various tiny sized USB memory sticks showed this worked very well (at least with the Pi 3b). But I was still concerned that if I had any wiring problems on competition day it would be difficult to access the internals to fix things.<br />
<br />
The idea I had to solve this was to redesign my chassis so that all the electronics were mounted on a plug-in cartridge which could be pulled out of the chassis to easily access everything. This also allowed me to design a second tier to mount breakout boards on above the Raspberry Pi.<br />
<br />
<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/AVvXsEi3rfBtru2oOuir9v0KoZ-Om5F-sgiDGN-N3tT7SVdYTiUTx_omvB9GIeTTUcic4uGb4O8B58gW955rfmNgXz73hoh11v8vMX4UAjhyphenhyphenDR6Uw-VKtBjccCK8jkND8paQ5OVB37-824UVVOE/s1600/Pi+tray.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="808" data-original-width="1070" height="482" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3rfBtru2oOuir9v0KoZ-Om5F-sgiDGN-N3tT7SVdYTiUTx_omvB9GIeTTUcic4uGb4O8B58gW955rfmNgXz73hoh11v8vMX4UAjhyphenhyphenDR6Uw-VKtBjccCK8jkND8paQ5OVB37-824UVVOE/s640/Pi+tray.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">CAD model of my electronics cartridge</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
Having a 2 tier electronics tray posed some problems with how to route the ribbon cable which connects the touch screen display to the Pi. I went through a few iterations before building a prototype cartridge. If I routed the ribbon cable straight up through the upper tier then it limited the space to arrange the breakout boards on that tier. I ended up with a design where the ribbon cable was folded to change the orientation through 90 degrees from the Pi to the display. The fold was contained on the lower tier, which required the height of the lower tier to be higher than originally planned. Space was tight for the upper tier, and I did not take into account the height of the Du Pont connectors used to attach all the wires to the breakout boards. Another redesign of my entire chassis was required to allow another 5mm of head room. I modelled just one Du Pont connector with a wire bending over coming from it (you can see it in the CAD model above) to check I had the required headroom for the wiring.<br />
<br />
<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/AVvXsEgH_cRrGNc6kbM4YjnfdZ6AKublOePSVEkKbhB_RgOIqoqvCRx9ipOwsH_JqJwk9Cr5_k4qzj2OEOtJEV8PWJQgSUnR5p1e5yUpxoCcNEEgPax9DkwrXn8_RDNXVgg-TDWcDEeYCo6WLZs/s1600/Chassis+v3.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="756" data-original-width="1024" height="472" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH_cRrGNc6kbM4YjnfdZ6AKublOePSVEkKbhB_RgOIqoqvCRx9ipOwsH_JqJwk9Cr5_k4qzj2OEOtJEV8PWJQgSUnR5p1e5yUpxoCcNEEgPax9DkwrXn8_RDNXVgg-TDWcDEeYCo6WLZs/s640/Chassis+v3.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Redesigned chassis with the electronics cartridge inserted</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
It all looked great in CAD, but when I came to assemble it I realised I needed a lot longer cables to provide enough slack to actually slide out the cartridge from the chassis. My ribbon cable was not long enough and 40 way ribbon cables seemed very expensive when I looked online at the usual electronics suppliers. Then I remembered somebody had pointed out that IDE hard disk cables in older PCs were just this type of cable. I checked my box of parts for modding PCs and found I had several. They all had 3 connectors, but I simply cut one off close to the middle connector to give a suitable length ribbon cable. All my other Du Pont connector leads I was making myself from a reel of ribbon cable, so I made these long enough to provide some slack.<br />
<br />
The reality was that all this extra cable took up a lot of room, and the cartridge was very tightly packed when assembled. It was very hard to slide out due to the cables all catching on bolts, and in hindsight I could have done with another 10mm of head room in the chassis. But I can just about slide it out with a lot of cable wrangling if required to plug in a new lead. I later extended the i2c breakout to a second bus board near the front of the chassis so that I could easily plug and unplug additional ic2 devices mounted on the front of the robot without needing to remove the cartridge.<br />
<br />
<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/AVvXsEiFube2ZAHoAfXApVdqHTJkMcvwkFN9WqyItCJ4WtUzshSxI8o1d0LbEwk9_jifVBjwqiCFS5ZdNLmUUb6vN8QLnF_LjHP9FGEQfZ9vUNYAExcHBtDc714Zo_LRE4snO5CNQmHg62L5pqc/s1600/IMG_2841.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFube2ZAHoAfXApVdqHTJkMcvwkFN9WqyItCJ4WtUzshSxI8o1d0LbEwk9_jifVBjwqiCFS5ZdNLmUUb6vN8QLnF_LjHP9FGEQfZ9vUNYAExcHBtDc714Zo_LRE4snO5CNQmHg62L5pqc/s640/IMG_2841.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-size: small;">The assembled electronics cartridge with the multiple folds in the long ribbon cable. Most of the i2c device cables are missing here, apart from one connecting to the PWM breakout used to drive the servos and motor power. The 4 servo cables are also missing here.</span></td></tr>
</tbody></table>
<br /><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/AVvXsEhk14XU6giX2gtOtnDYAI08mDHLYsiWpj4XN3yGgfcD2x1Kp7pHdEx7SsYEcR-uvDXZ6VzllG045c1hDCXfv215-y-ri6OxC1Db195OvP0639k5Tya-Mxv2uUPE5zngupkPXJmmb71hKAM/s1600/IMG_2965.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk14XU6giX2gtOtnDYAI08mDHLYsiWpj4XN3yGgfcD2x1Kp7pHdEx7SsYEcR-uvDXZ6VzllG045c1hDCXfv215-y-ri6OxC1Db195OvP0639k5Tya-Mxv2uUPE5zngupkPXJmmb71hKAM/s640/IMG_2965.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-size: small;">Shown with the chassis front and front-side panels removed. The cables completely pack out the space in the cartridge.</span></td></tr>
</tbody></table>
<br />
<br />
<br />Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-78388472475264232522019-03-12T13:15:00.000-07:002019-05-31T05:06:21.988-07:00Robot Software DesignI went for a modular design for my robot software. Python is very modular in structure, with each module importing the modules (or code libraries) it requires. I designed my robot software along the following lines.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOwq_xN4-sbktt0o-0mtaXZdQQGrHswyPkgs7JXPlo9WuYScC1nioeGCHcNLRSABMO2xPrzSB1GTkQxSKmOr2oh4xwSlT_VltoPFSkt8WzFiF-pMsr9Pk_sYhTLz1eKvqYqqbg8CCAB6c/s1600/Software+Modules.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="889" data-original-width="889" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOwq_xN4-sbktt0o-0mtaXZdQQGrHswyPkgs7JXPlo9WuYScC1nioeGCHcNLRSABMO2xPrzSB1GTkQxSKmOr2oh4xwSlT_VltoPFSkt8WzFiF-pMsr9Pk_sYhTLz1eKvqYqqbg8CCAB6c/s400/Software+Modules.png" width="400" /></a></div>
<br />
<br />
Each module does a specific job, and is accessed through a few simple functions which describe the operation being performed. For example the Sensors module contains a function readDistance(sensor) which returns the distance measured by one of the TOF (time of flight) sensors. The parameter (sensor) specifies which sensor (by number) to read. The module also provides the required methods to configure and initialise the sensors, and the i2c multiplexer board they are connected to. So all the complexity of switching i2c buses, turning on sensors and reading them is wrapped up in a module with a very simple code interface.<br />
<br />
Another advantage of a modular approach is that you can put all the code which is specific to a set of hardware (e.g. motor controllers) in a single module. The module then presents an interface with simple methods like setMotorSpeed(motor, speed). If you need to change the motor controllers used in your robot, or want to reuse the code on another robot with a similar arrangement of twin motors then you only need to replace this one module and the rest of the code can be reused without changes.<br />
<br />
The hardware interface module is called from a module which represents the movement capabilities of the robot. In this case my robot has steerable wheels, and multiple motors wired up in two groups. So the movement control of the robot is wrapped up and controlled through a few simple functions:<br />
<br />
<ul>
<li>setLeftMotorPower(speed)</li>
<li>setRightMotorPower(speed)</li>
<li>setSteering(angle)</li>
<li>setSpotTurn(angle)</li>
</ul>
<br />
The LED Matrices module handles setting up and connecting a pair of rgb 5x5 LED matrix breakouts, and displaying patterns on them. A series of patterns are stored in the module and can be called by name. There is also a frame buffer which allows series of patterns to be queued up to show on the LEDs one after the other. Methods can be added to queue up patterns by name. e.g. showBlueEyes() or eyesBlink(). Animations cycle through the frames in the buffer for each display when a nextFrame() method is called.<br />
<br />
The main program module handles output onto the main display screen. It also contains all the event handler functions for controller input. A separate module handles detecting different game controllers and mapping their buttons, sticks, hats and triggers to the same named events. So a range of game controllers can be used on the robot and they will all call the same code when their 'triangle button' is pressed.<br />
<br />
The main module also contains the code for reacting to touchscreen input to display and navigate through graphical menus, and the main program loop which takes actions based on the mode the robot is in. In this main loop, sensors reading calls can be made, there is the call to display the next frame on the LED matrices, and trigger calls to any event handlers for the connected game controller.<br />
<br />
Developing all the code for menus, modes and linking controller input to the robot can be very time consuming when trying to test on the robot itself. But by having the modular structure we can create a virtual copy of our robot, or Digital Twin. By writing a mock copy of each module which interfaces to the actual hardware we can work on the code without the robot being present at all. I did a lot of the coding on a laptop using Raspbian x86 running in a VirtualBox VM. Coding anytime, anywhere. Only the laptop was needed to write, debug and test much of the code.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvHN6gUByPlGvkdfPWPPt6S7ZVyOX0tLqYSUYn5Q03bteHv3fmSL7d76E4k_q0LeTgvJoR1Oz8Lh3nIsa_XicKHMC9Ke3tfRAS4Drft_QDqsGFl8HWDizbv1T7fDBBZqhV0_qLg0SNkrI/s1600/Software+Modules+Virtual.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="889" data-original-width="889" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvHN6gUByPlGvkdfPWPPt6S7ZVyOX0tLqYSUYn5Q03bteHv3fmSL7d76E4k_q0LeTgvJoR1Oz8Lh3nIsa_XicKHMC9Ke3tfRAS4Drft_QDqsGFl8HWDizbv1T7fDBBZqhV0_qLg0SNkrI/s400/Software+Modules+Virtual.png" width="400" /></a></div>
<br />
<br />
Just 3 modules (coloured blue above) needed mock versions to the written for the robot to be virtualised. Each of these mock modules has the same name and functions in it as the real version. But the code inside the functions captures the display object from pygame and renders a representation of itself onto the display.<br />
<br />
<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/AVvXsEhnTCOMzNrlN-SfkROMpLfhn0ivB79_qtU5GItfb-j0nlz5mhKUpLN5WTvSdluaIgsambmJ6dUPlv3Oq0WCTv5G5csr7bPLG3_e10zzs6bZEIupAx_U2dekR0t0rD0xPVi2oNMKeEDjyP8/s1600/DigitalTwin.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="479" data-original-width="799" height="383" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnTCOMzNrlN-SfkROMpLfhn0ivB79_qtU5GItfb-j0nlz5mhKUpLN5WTvSdluaIgsambmJ6dUPlv3Oq0WCTv5G5csr7bPLG3_e10zzs6bZEIupAx_U2dekR0t0rD0xPVi2oNMKeEDjyP8/s640/DigitalTwin.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Digital Twin: A virtual representation of the robot<br />
<div style="text-align: right;">
(Background Mars image from Hubble Space Telescope. Credit: NASA)</div>
</td></tr>
</tbody></table>
<br />
The mock hardware interface module renders the shape of the robot, and shows the motor speeds and steering leg angles. The mock sensors module generates randomly varying distance readings and renders yellow triangles to indicate the sensor values. The rgb LED matrix mock module renders a representation of each LED matrix onto the screen. I also added an option to display numerical information to aid debugging and diagnosing problems. You can see the virtual robot running in this video clip I posted on Twitter:<br />
<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en" style="text-align: left;">
Coding my robot using a digital twin is so much easier. Just added a data debugging mode which overlays status informational the screen (the white text). The graphical robot is my digital twin mock for my hardware. I’ll upload the working code to the real robot later. <a href="https://twitter.com/hashtag/PiWars?src=hash&ref_src=twsrc%5Etfw">#PiWars</a> <a href="https://t.co/hWdX5cMObw">pic.twitter.com/hWdX5cMObw</a></div>
<div style="text-align: left;">
— Dr Footleg (@drfootleg) <a href="https://twitter.com/drfootleg/status/1098282841484472320?ref_src=twsrc%5Etfw">February 20, 2019</a></div>
</blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<br />
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
The graphical representation of the digital twin of my robot and the sensor output was so useful for debugging issues that I moved it from the mock module into the main robot module. All the graphics slow down the main loop so that it does impair the responsiveness of the robot. So I made it possible to switch on and off via the controller. In normal running the display shows a static graphic of a solar panel, as you can see in this video clip.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dw0V7g5UI3BdFDhAmpPjj3OUN_l7DQo_YfC6v0OisB4-tdpZih5UyvPWhKPp0uSqEumLxNBIk-UD3ElaXa7BQ' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />
(Post Pi Wars 2019 competition I published the full source code for my digital twin robot on github. You can play with my virtual robot using the code on the 'mock' branch. Full instructions and code here: <a href="https://github.com/Footleg/PiWars2019/tree/mock">https://github.com/Footleg/PiWars2019/tree/mock</a> )Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-23789683901495029002019-03-11T06:35:00.003-07:002019-03-11T06:35:49.820-07:00First Fully Drive-able Build of my Mars RoverMy first prototype body to mount my rocker bogie arms onto made me realise I needed to better balance the weight of my robot over the main pivot axis. I also needed better clearance between the body and the steering legs. Then there was the challenge of where to put the rest of the electronics and the battery. I decided the battery was the thing to provide the weight to counter balance the body, and being a heavier item should also be located closer to the ground to make the robot more stable. So I drafted a design where the rear of the body was tapered giving less width. Enough to accommodate the battery but narrow enough to give sufficient clearance for the rear steering legs.<br />
<br />
<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/AVvXsEjfl4ezPHmmswQvf4ghRFfnMspmgyzHlmjEN5l-DVoEE4MrMTBZgQsDXfvp5VdqFNz-gesnpTwtqebfGs86BHupOlDVoOMpH2HjdyrTFWY1SWGsQ2YPn1zNSymp-mnrqu-xhZYJh8RkDzE/s1600/IMG_2455.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1255" data-original-width="1600" height="502" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfl4ezPHmmswQvf4ghRFfnMspmgyzHlmjEN5l-DVoEE4MrMTBZgQsDXfvp5VdqFNz-gesnpTwtqebfGs86BHupOlDVoOMpH2HjdyrTFWY1SWGsQ2YPn1zNSymp-mnrqu-xhZYJh8RkDzE/s640/IMG_2455.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Early redesign of main body with narrower rear end</td></tr>
</tbody></table>
<br />
In attempting to wire up all the motors, and with the steering servo cables also needing routing into the chassis body, my robot was suddenly looking rather messy. I had deliberately made my prototypes from 3mm ply so they could be modified easily to iterate on the design. I explored ways to route the motor wires by getting out the drill.<br />
<br />
<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/AVvXsEh3bakbOTm9EYMV2FNPlRBFKLjK9zgLWv5aCz_8DQS8l-rMHWNG9_YnYYiP2MedG9xLdzgQ1BsBMo09GtqL97naHAB2kCfP_1Njw9i-9ZSYnPLsghWzN0xBm4IjoROsuHqUcaZw4P0aQwI/s1600/IMG_2471.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3bakbOTm9EYMV2FNPlRBFKLjK9zgLWv5aCz_8DQS8l-rMHWNG9_YnYYiP2MedG9xLdzgQ1BsBMo09GtqL97naHAB2kCfP_1Njw9i-9ZSYnPLsghWzN0xBm4IjoROsuHqUcaZw4P0aQwI/s640/IMG_2471.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Iterative design: wire routing!</td></tr>
</tbody></table>
<br />
Somebody commented on one of my Twitter posts asking where I planned to mount the Pi Noon attachment required for two of the challenges. This was not something I had considered up to this point. The <a href="https://piwars.org/2019-competition/challenges/pi-noon/" target="_blank">challenge rules</a> stated the attachment point had to be on the front of the robot, in the middle. My robot design at this point had nothing but thin air in that position! I wondered about making some sort of brace which attached to the two front rocker arms to hold it. This would lock the rocker (but the event would have a flat surface so not a big issue). Then I realised it was also needed for the <a href="https://piwars.org/2019-competition/challenges/spirit/" target="_blank">Spirit of Curiosity</a> challenge and this was expected to have terrain of varying difficulty. This was the challenge my robot was built for, and my robot was based on the namesake Mars rover of this challenge. I needed another plan. Looking at pictures of the real Mars Curiosity rover I realised that the rocker arm linking bar was positioned forwards of the main pivot axis, rather than behind as on my rover. I swapped mine to the same (you can see this difference between the original animated CAD model and the actual plywood first prototype in my <a href="https://adventures-with-pi.blogspot.com/2019/02/designing-main-chassis-and-complete.html" target="_blank">earlier post</a>).<br />
<br />
<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/AVvXsEg7LmgNZLTLRsyJRLD8auWG1X1HWk7pPR7eWCfZTPt0XVfBka_h08JPotv3C7zQYTzWcsmtOdBswwjojLHaBtKQvUKvlb-Ze8xdqwA8gArhbN_fmK9GYQmsEx0QnawMAqgz2LXknNfZ2KQ/s1600/Chassis+v2.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="782" data-original-width="1038" height="482" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7LmgNZLTLRsyJRLD8auWG1X1HWk7pPR7eWCfZTPt0XVfBka_h08JPotv3C7zQYTzWcsmtOdBswwjojLHaBtKQvUKvlb-Ze8xdqwA8gArhbN_fmK9GYQmsEx0QnawMAqgz2LXknNfZ2KQ/s640/Chassis+v2.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Redesigned chassis shape with battery compartment and room for breakout electronics</td></tr>
</tbody></table>
<br />
Looking at my remodelled chassis it suddenly struck me that the back looked awfully like a front now, and what I had always imagined as the front was looking much more like the back (complete with USB and ethernet 'exhaust' ports). This now gave me a front panel to attach the Pi Noon attachment to as well. I extended the new front end to bring it level with the end of the rocker arms, and so my final rover shape was decided.<br />
<br />
<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/AVvXsEis10HhhQrXVkX0ThiOjIG1EVUy8ns0YiuQNmmJkttOcxYl-SHYTRyxg3JjDKV2ykIstoMrLqlC_FCPNafiSO1I6ZRHMjnAAvWSFRDyMBfEEIIjo57utl20lmvF_v9Mu0CJ9Rzoi6bO4UY/s1600/IMG_2501.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis10HhhQrXVkX0ThiOjIG1EVUy8ns0YiuQNmmJkttOcxYl-SHYTRyxg3JjDKV2ykIstoMrLqlC_FCPNafiSO1I6ZRHMjnAAvWSFRDyMBfEEIIjo57utl20lmvF_v9Mu0CJ9Rzoi6bO4UY/s640/IMG_2501.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The new completed chassis built and ready for some road testing</td></tr>
</tbody></table>
<br />
<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/AVvXsEgGihgsQcw6iU5PEvTBpBOtRIMyNcHTN-6CuzVHsZftXSSiAjyppuJ9C9FtMCpw6O_o4xrWeTHJddXSs3nRrZlyMUpc7l8JScu5jtXF5K4vWYZXmWFuZosU_GC7gVceN0ijJ9OTfxLDKsY/s1600/IMG_2503.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGihgsQcw6iU5PEvTBpBOtRIMyNcHTN-6CuzVHsZftXSSiAjyppuJ9C9FtMCpw6O_o4xrWeTHJddXSs3nRrZlyMUpc7l8JScu5jtXF5K4vWYZXmWFuZosU_GC7gVceN0ijJ9OTfxLDKsY/s640/IMG_2503.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Checking the A4 footprint of my new design</td></tr>
</tbody></table>
<br />
Finally I had something I could road test. The closest thing I had to some martian terrain was a load of rocks and fossils collected on family trips to the Jurassic coast.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/Rk65fSdXRQk/0.jpg" src="https://www.youtube.com/embed/Rk65fSdXRQk?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br />
Overall I was very pleased with how well my robot handled. It was very easy to control. The grip on steeper slopes was not enough, but I think for the Pi Wars challenges it will be sufficient. It was a little top heavy and prone to toppling over on more challenging obstacles. Here are some of the out-takes.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/-Z87YErqRIM/0.jpg" src="https://www.youtube.com/embed/-Z87YErqRIM?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br />Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-56938002445792374572019-02-18T15:05:00.000-08:002019-02-18T15:05:50.185-08:00Pi Wars Robot Electrical Design<br />
The fundamental components I needed for my raspberry Pi based robot were a Raspberry Pi board, a servo driver board and dual motor controllers. On top of this there would be various sensors and a camera. I decided early on I wanted some sort of display and buttons to control a menu system on the display to set the various modes of the robot for different challenges. The display I chose was the <a href="https://shop.pimoroni.com/products/hyperpixel-4" target="_blank">HyperPixel 4.0</a> touch screen display which Pimoroni had just released. This would give me a beautiful full colour display and the touch screen would enable me to use the screen itself to select menu items.<br />
<br />
The next decision was how to power the robot. I had learned from other people of the problems with using a power source for the Pi shared with the motors. If the motors draw too much power then the supply to the Pi can dip, causing reboots or crashes. One way to avoid these problems is to provide a completely separate power supplies to the Pi and to the motors/servos. But this is not necessary provided the power supply can provide enough power for all components at their full loads. I decided to use a high discharge current LiPo battery. I planned to use UBECs (Universal Battery Eliminator Circuit) to eliminate the need for different battery voltages. I could supply 5V to the Raspberry Pi using one UBEC, and 6V to my motors and servos using a second UBEC. I already had experience using the cheap Hobbywing 3A 6V/5V switch mode UBEC for robots. These are readily available online (<a href="https://www.ebay.co.uk/sch/i.html?_from=R40&_nkw=hobbywing+ubec&_sacat=0" target="_blank">try eBay</a>). I tend to buy 10 at a time from China so I have a stock of them in my parts box ready for projects.<br />
<br />
<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/AVvXsEi-ZiYdcMNMNPmWUe6ga5Hs3DJqpECFk_PbE1E-dbSztjK3eXaoDv8djnmndWvuLcxRiyjPoEIlvJBPkx4d-nhto2YzVtLvOFCMauC6IZo6qICtvA0u5bHr4gyx2iX1CqDGdKLXuR_k9CI/s1600/IMG_2495.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-ZiYdcMNMNPmWUe6ga5Hs3DJqpECFk_PbE1E-dbSztjK3eXaoDv8djnmndWvuLcxRiyjPoEIlvJBPkx4d-nhto2YzVtLvOFCMauC6IZo6qICtvA0u5bHr4gyx2iX1CqDGdKLXuR_k9CI/s640/IMG_2495.JPG" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Early prototype wiring to test the servo and motor drivers, powered by a LiPo battery and two UBECs</td></tr>
</tbody></table>
<br />
For the motor drivers, you need to choose some which can supply the voltage your motors require and handle the maximum current which the motors can pull. My robot was using 6V rated micro metal gearmotors with 1:50 ratio gear boxes. According to the <a href="https://shop.pimoroni.com/products/micro-metal-gearmotor-extended-back-shaft" target="_blank">listing</a> on the Pimoroni website these have a stall current of 770mA. Stall current is the current the motors will draw if they are fully powered and the shaft is prevented from turning. Typically this can happen if the robot is trying to drive up too steep a slope or into an obstacle which prevents it moving, so all motors could draw this current at the same time. My design had them wired up as 2 pairs of 3 motors in parallel, so I needed a 6V supply to the motors and a maximum stall current of 3 x 770mA = 2.3A. I already had a pair of <a href="https://www.adafruit.com/product/3190" target="_blank">Adafruit DRV8871</a> motor driver breakout boards, capable of supplying up to 3.6A per board. The UBEC circuit can supply a steady 3A at 6V so I would need a UBEC per motor driver. I built a test circuit for a single motor and found it did not work. Reading the specifications of the motor driver board again I realised if needed a minimum of 6.5V input voltage. So my UBEC regulating the voltage down to 6V would not work.<br />
<br />
Some discussions on Twitter led me to the decision to drive the motors directly off the battery voltage. This could be as high as 8.2V when fully charged, but seeing as the software would limit the motor power using PWM anyway I could set a limit to prevent the motors getting the full power of the battery. They would still be getting peaks of more than 6V during the on-cycle of the PWM signal, but the motors are not such sensitive components that this should be a problem, and I had been advised that these motors could be over-driven safely at these voltages. At a higher voltage I would have more speed, more torque but also a higher stall current. But I would not need a UBEC per motor driver now. The driver boards I had can supply up to 45V to motors, and up to 3.6A so this should work fine.<br />
<br />
Next I looked up the HyperPixel touch screen board on the excellent <a href="https://pinout.xyz/pinout/hyperpixel4">pinout.xyz</a> website to find out which GPIO pins it used on the Raspberry Pi. The answer turned out to be all of them! But it did break out the software i2c bus so I still had the option to control i2c hardware from a Pi using this screen. I was already planning to drive the servos using an <a href="https://www.adafruit.com/product/815" target="_blank">Adafruit 16 channel 12 bit PWM</a> servo driver board which is an i2c device, so that should work. But I had no GPIO outputs available on the Pi to drive the motor driver boards. I discussed some options with Brian Corteil of <a href="https://coretecrobotics.co.uk/" target="_blank">Coretec Robotics</a> at one of the monthly robot club sessions he organises at <a href="http://makespace.org/" target="_blank">Cambridge Makespace</a>. These included the following:<br />
<ul>
<li>Use an Arduino to provide some additional PWM outputs</li>
<li>Use a second Raspberry Pi to connect sensors and drive the motors</li>
<li>Use an i2c GPIO extender breakout board</li>
</ul>
Then it occurred to me that what I needed to drive my motors were digital PWM outputs, and this is exactly what the 16 channel PWM board I was planning to use to drive my steering servos had in abundance. I built a test circuit on a breadboard to experiment with this. I made a mistake thinking I would drive the servos at 6V, because while the motor driver boards can drive motors at up to 45V, the logic inputs to the board are only rated up to 5.5V. My 6V PWM output damaged one of the boards and I had to replace it. My steering servos were plenty fast enough and strong enough using a 5V supply, so I switched the UBEC supplying power to the servos back to 5V.<br />
<br />
The last piece of the puzzle was how to drive multiple laser time of flight distance sensors over i2c when the boards I had chosen (the <a href="https://shop.pimoroni.com/products/vl53l1x-breakout" target="_blank">VL53L1X</a> breakout by Pimoroni) had a fixed address. I read it is possible to switch this address on power up, but this presumably required powering up each sensor board in turn, and that would require more digital outputs which I did not have. An easier solution was to use an i2c board which provides switchable i2c buses, and I chose the <a href="https://www.adafruit.com/product/2717" target="_blank">TCA9548A I2C MULTIPLEXER</a> from Adafruit.<br />
<br />
To connect up all my i2c devices, and supply power to the Raspberry Pi, I made a small power and i2c bus breakout board using strip-board. I built this with 5 pin connectors to match the Adafruit PWM board and Pimoroni range of i2c breakouts which all have 5 pin headers including an interrupt line.<br />
<br />
<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/AVvXsEihIa4mFy-4FvJX7AcI7uDTqrKH20MG8e_a0_-5-4g0nFDT_O0puKFUXrLrcqFoamE2dVL8EOLwl7BnCkNYOgyINh91Rp0FRbSeMORCUIXp5OAoptWZGq5HPxhTxzoLRbqzN0z2YcEQEbM/s1600/IMG_2816.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1104" data-original-width="1600" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihIa4mFy-4FvJX7AcI7uDTqrKH20MG8e_a0_-5-4g0nFDT_O0puKFUXrLrcqFoamE2dVL8EOLwl7BnCkNYOgyINh91Rp0FRbSeMORCUIXp5OAoptWZGq5HPxhTxzoLRbqzN0z2YcEQEbM/s400/IMG_2816.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">i2c and power bus board</td></tr>
</tbody></table>
<br />
The UBEC supplying power to the Pi and screen was connected to this, and power supplied over the i2c V+ and GND lines to all components. You can see the complete wiring diagram below.<br />
<br />
<br />
<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/AVvXsEgsCZrAT-QixiOX1ynhm81UAE_W6uWSSWKkjm6Dt30n2YdLwHwShyphenhyphenVBmI4108Hgc_BpIsR9Z1kyAuGyJnNBYqYOvuSWWDRbD7S9EAqtijwTomX8u9FfjjOcDy_VQdjm787pIhQv0aFesQ4/s1600/Electrical+Design.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="762" data-original-width="1200" height="406" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsCZrAT-QixiOX1ynhm81UAE_W6uWSSWKkjm6Dt30n2YdLwHwShyphenhyphenVBmI4108Hgc_BpIsR9Z1kyAuGyJnNBYqYOvuSWWDRbD7S9EAqtijwTomX8u9FfjjOcDy_VQdjm787pIhQv0aFesQ4/s640/Electrical+Design.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The electrical design for my robot (click to see larger version)</td></tr>
</tbody></table>
<br />
In order to mount the display on top of the robot, I soldered up a right angle GPIO connector using a Pimoroni <a href="https://shop.pimoroni.com/products/pico-hat-hacker" target="_blank">Pico HAT Hacker</a> board which enabled me to connect the display to the Raspberry Pi using a ribbon cable. I soldered a second 4 wire ribbon cable onto this connector to supply power to both the Pi and the display, and to connect the software i2c bus to my breakout bus board. I was relieved when I connected this all up and saw it working as intended.<br />
<br />
<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/AVvXsEi8DivOvLP8awBK-PtTV-rDbPX7eEPyIEsD8hIZaSCp3J_OEiuMatiLZ1rhaVOGhKo7ccPZr-nR_lrWxpizQ9wXMZ84BqZthXMs_oOH6k8YB7ejQqSFFxulS0Rmt8bQZY9RoASg7dkXmdQ/s1600/IMG_2823.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1037" data-original-width="1600" height="414" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8DivOvLP8awBK-PtTV-rDbPX7eEPyIEsD8hIZaSCp3J_OEiuMatiLZ1rhaVOGhKo7ccPZr-nR_lrWxpizQ9wXMZ84BqZthXMs_oOH6k8YB7ejQqSFFxulS0Rmt8bQZY9RoASg7dkXmdQ/s640/IMG_2823.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Working display and Pi powered via the i2c bus and power breakout board</td></tr>
</tbody></table>
<br />
The next challenge was going to be how to fit all this electrical hardware and connecting wiring into my robot chassis.Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com2tag:blogger.com,1999:blog-3131866441334625691.post-15508426510333931092019-02-16T13:02:00.000-08:002019-02-16T13:02:02.704-08:00Designing the Main Chassis and Complete Rocker Bogie AssemblyHaving built a pair of working prototype rocker bogie wheel assemblies, I turned my attention to the main body of the rover. Initially I just used a simple box shape, keeping the front of the chassis well back from the front steerable wheels to avoid collisions. The rear of the chassis had to overlap the area where the rear steerable wheels servo links came under the body in order to fit the top pivot for the linking bar assembly. But I now had a basic chassis design which enabled me to complete my CAD model and see a working mechanical model of the full rocker bogie suspension.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbWpN7zAYuXq0SJGwUlLXx0_tWxNjv9DJWwr2vtYPzjzEd2INcM0asl3ysaxxnMCSm9t9KYlNPUJpgKU8ThAtA-i5UVOW3F3-M5GV-DyshuDynb5JPjATFmwjnsxW0xIuJkBLuDlVGXDw/s1600/Rover1bAnimation.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="198" data-original-width="289" height="273" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbWpN7zAYuXq0SJGwUlLXx0_tWxNjv9DJWwr2vtYPzjzEd2INcM0asl3ysaxxnMCSm9t9KYlNPUJpgKU8ThAtA-i5UVOW3F3-M5GV-DyshuDynb5JPjATFmwjnsxW0xIuJkBLuDlVGXDw/s400/Rover1bAnimation.gif" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
A rendered animation of the rocker bogie suspension</div>
<br />
To avoid the rear wheel steering links colliding with the underside of the body, I modified the box so that the bottom was shorter than the total length of the body. This gave the servo steering links more clearance where they passed under the body. I made the front section of the body just long enough to fit in the Raspberry Pi 3 plus two additional support pillars to provide a second pair of holes for the main pivot bolts to pass through. This gave a more rigid main pivot axis assembly than if the bolts just passed through one piece of 3mm sheet material on each side.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKKmwo3bPjIYKveZoY3O273j863npglD-RWirwv4an8sA11ntpmeTY-iBKtWbnAU66SiQMEtLSdsLb64_zgP2aiczB8QmGGSc4A5LqXwjmob_-U7ARDTgwcrT6dYX0b3IgJVjC3pzilqc/s1600/IMG_2438.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1291" data-original-width="1600" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKKmwo3bPjIYKveZoY3O273j863npglD-RWirwv4an8sA11ntpmeTY-iBKtWbnAU66SiQMEtLSdsLb64_zgP2aiczB8QmGGSc4A5LqXwjmob_-U7ARDTgwcrT6dYX0b3IgJVjC3pzilqc/s400/IMG_2438.jpg" width="400" /></a></div>
<br />
I mounted the Raspberry Pi 3 board in the box, with the USB and Ethernet ports poking through a cut out. This was technically the first Raspberry Pi case I had ever designed. The rear of the box still needed to extend far enough back to support the linking bar assembly on the top. To allow this, the base of the box stepped up to a lesser depth at the rear.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBK2f0jpFfO2Z8orKlWbkjdS3x1wVCYot98qy7PoA7NXBmgdnkuLdt9Ep-a-iELmWlgQqEAVvqvOVE38L7rAZF5wxLcH510WJklC6tp0qD1YyCckCp41dt2Hrzm2eymfEDw6qLv1cf4bc/s1600/IMG_2437.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBK2f0jpFfO2Z8orKlWbkjdS3x1wVCYot98qy7PoA7NXBmgdnkuLdt9Ep-a-iELmWlgQqEAVvqvOVE38L7rAZF5wxLcH510WJklC6tp0qD1YyCckCp41dt2Hrzm2eymfEDw6qLv1cf4bc/s400/IMG_2437.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
The body design with a step up on the underside at the rear </div>
<div class="separator" style="clear: both; text-align: center;">
to allow the steering links to pass underneath the chassis</div>
<br />
At this stage I was still pondering over how to build the linking bar assembly. I had modelled a bracket to hold the horizontal linking bar, which I was going to have to 3D print. I also needed to solve how to attach fittings to the ends of the cylindrical bar to link to the rocker arms. At about this time, somebody posted a picture of the NASA Mars Curiosity rover in a lab in reply to one of my progress posts on Twitter. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFh2Hq6EKvz1J1bCZBsWM469EsK9DE8QEXpFgJYCfBv4dZ-di_SlKwUvZ-fAzo1t7jZWPPRvut5FowiZdSNjKXo5biWAqW9sGAC45vUsUdWlh_poFZHFFW2CaF7Smc_QYDDjFUUMB2VME/s1600/nextmarsrove.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="710" data-original-width="946" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFh2Hq6EKvz1J1bCZBsWM469EsK9DE8QEXpFgJYCfBv4dZ-di_SlKwUvZ-fAzo1t7jZWPPRvut5FowiZdSNjKXo5biWAqW9sGAC45vUsUdWlh_poFZHFFW2CaF7Smc_QYDDjFUUMB2VME/s640/nextmarsrove.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
Image Credit: NASA/JPL-Caltech</div>
<br />
Up to this point I had not realised how large the real Mars Curiosity rover was! But I also noticed the linking bar was a flat bar, not a metal rod as I had modelled based on the JPL educational scale model project which inspired me to design a Pi Wars sized version of my own. That looked a lot easier to build. The picture also gave me another revelation. I did not need to mount the bar on the back of my rover. It could go in front of the main pivot axis of the body. This gave me more room as the body already extended further out in that direction to accommodate the Raspberry Pi. It also better distributed the weight of the body between the horizontal pivot axis and the top mounting point for the linking bar.<br />
<br />
I now had a complete design worth building a prototype of. I laser cut it all from 3mm plywood because this was cheaper than plastic, easier to modify with small tools after cutting the pieces and I could re-purpose all the off-cuts and waste pieces as kindling to light the fire at home.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP5_K5jyHZICUGo9l8yAed3JgMO2KSSqEYbByhGAxwh5WNHgu4qlNUyT9XoK3EYjMMXp7z8gN_hJQzNI1qXI1nFBOaR4JaQTb6fTJEDBDUTee7KRjv9355cReKNJc4Y3pq8o5ZNrbYqys/s1600/IMG_2444.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP5_K5jyHZICUGo9l8yAed3JgMO2KSSqEYbByhGAxwh5WNHgu4qlNUyT9XoK3EYjMMXp7z8gN_hJQzNI1qXI1nFBOaR4JaQTb6fTJEDBDUTee7KRjv9355cReKNJc4Y3pq8o5ZNrbYqys/s640/IMG_2444.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
My first prototype, almost fully assembled (one rocker bogie arm is attached here)</div>
<br />
This first mechanical prototype enabled me to verify that the design worked in practice. It also allowed me to test how much motion was possible in the rocker bogie arms before the rear steering legs collided with the underside of the chassis. I was not sure there was enough range of movement, and it also made me realise the weight was not well balanced around the main pivot axis of the chassis. I needed to think about how to solve these problems, and also work out how to fit all the electronics and a power source into the body.Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-1309608321827519222019-02-13T11:26:00.000-08:002019-02-13T11:26:02.802-08:00Refining My Rocker Bogie DesignUsing my newly learned skills in CAD and laser cutting I started to build the rocker arms for my robot. I was pleased with the way my servos fitted into the arm, but concerned that using the servo itself as the only mounting point for the steering leg was not going to be strong enough. That tiny screw attaching the horn to the servo just did not feel like it would handle all the strain put on the robot leg.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8v7KvmiUiOvfPR14KFvmgaTmvVlYLRRnYDlP_o6kJGf55Z7Bq43mOxxSnw8Hv2YwpcyQJ-gFzNjwnoxwztkrUCXiJdWEOacAk5tV6T8UN1dOtWMEt1quoosLdXSZR4cF7HdPlywER7B4/s1600/IMG_2389_cropped.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="778" data-original-width="1224" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8v7KvmiUiOvfPR14KFvmgaTmvVlYLRRnYDlP_o6kJGf55Z7Bq43mOxxSnw8Hv2YwpcyQJ-gFzNjwnoxwztkrUCXiJdWEOacAk5tV6T8UN1dOtWMEt1quoosLdXSZR4cF7HdPlywER7B4/s400/IMG_2389_cropped.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;">My first prototype steering leg assembly</span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
I had only attached one leg to the first part of an arm and already I was needing to redesign. Some browsing of possible bolt styles I might use online led me to shoulder bolts. These have a solid cylindrical section (the shoulder) with a short threaded section on the end. I redesigned my leg and arm ends to attach the leg using a long shoulder bolt as the axis. A nylon spacer provided the required separation of the leg from the arm. Moving the servo along enabled me to attach the servo horn to the leg via a hinged link. The shoulder bolts were also perfect for the other pivots in the rocker bogie arms. So with the entire arm remodelled in my CAD software I was ready to assemble a complete version.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8qQNMpKP2PFN3kN8vvF4nlguvrQNp4K7uHZ8aQXVJWarDBLJgkGYQ4CRffbIxz27YVILlUQfxjaYw9X3dswKko6MoJhoVrtC4sF9uOpFmUj27n8hcBvHFMQYa8Q1pW44QvE3hYZww47w/s1600/RockerBogie2CAD.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="560" data-original-width="896" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8qQNMpKP2PFN3kN8vvF4nlguvrQNp4K7uHZ8aQXVJWarDBLJgkGYQ4CRffbIxz27YVILlUQfxjaYw9X3dswKko6MoJhoVrtC4sF9uOpFmUj27n8hcBvHFMQYa8Q1pW44QvE3hYZww47w/s640/RockerBogie2CAD.jpg" width="640" /></a></div>
<br />
My first attempt to put it all together in laser cut 3mm plywood proved that the design would work, but I could not fit the nuts onto the small bolts which held the servo mounting plates in place. I had not left enough room for the nuts to fit alongside the spacers on the pivot bolts. It was at this point that I discovered the collision detection feature of the CAD software and sure enough it highlighted the problem in my CAD model. Lesson learned I made some more adjustments and was finally able to build and assemble a complete pair of rocker bogie arms.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1Wl4TjZa88q3VNSDXL8zop8zMs_VzALtCs8lcqMAbVgezmYeytpsElRavpxQCvv5pdjKopcUMz-BKw9SFm_zRO21_Tqla93w6ybsAYV547nRyq92rbmN5YysHJdCBrlAt12NZz39yZlY/s1600/IMG_2451_cropped.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1062" data-original-width="1600" height="424" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1Wl4TjZa88q3VNSDXL8zop8zMs_VzALtCs8lcqMAbVgezmYeytpsElRavpxQCvv5pdjKopcUMz-BKw9SFm_zRO21_Tqla93w6ybsAYV547nRyq92rbmN5YysHJdCBrlAt12NZz39yZlY/s640/IMG_2451_cropped.jpg" width="640" /></a></div>
<br />
<br />Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-73503025344440850072019-01-21T13:28:00.000-08:002019-01-21T13:28:27.391-08:00CAD to Laser Cutter and KerfThe same week I learned I had got into Pi Wars 2019 I also managed to grab a place on a training session for the laser cutters at MakeSpace. These were the machines I had primarily wanted to use to make my robot when I joined MakeSpace and now I had done the induction I just needed to work out how to convert my CAD model into a file format I could use on the laser cutter. Or so I thought.<br />
<br />
The first problem was how to turn a 3D model of a part into a 2D outline for cutting. I was using SolidWorks CAD software and this has a drawings feature where you can generate 2D engineering drawings for different views of the parts and assemblies you have modelled. These drawings automatically update based on any changes you make to the modelled parts, which is very handy. But the file format for SolidWorks drawings is not supported by the software which the laser cutter uses. So the drawings had to be saved in a intermediate format which can be imported into the laser cutter software. Initially I was doing this directly as DXF format. A simple 'Save As' from SolidWorks to create a file I could import into a laser cutter project.<br />
<br />
I cut the parts of one of the forward arms of my rocker bogie suspension which needed to hold a servo, and the parts assembled around the servo perfectly. It was all going very well.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2eD_v3g9TSKaC0h6gKwLYOOwpoUv4hIn18Z0TEt-yg0gdESoeedZakiX0hD4a7ibInEd3a8aLFpZVf6d1iU1wPfisxWxPQ-Haf0d3dBzbLgMbMMMpCr892dWYtwh9dDg9wbuZW793YuI/s1600/IMG_2241.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2eD_v3g9TSKaC0h6gKwLYOOwpoUv4hIn18Z0TEt-yg0gdESoeedZakiX0hD4a7ibInEd3a8aLFpZVf6d1iU1wPfisxWxPQ-Haf0d3dBzbLgMbMMMpCr892dWYtwh9dDg9wbuZW793YuI/s400/IMG_2241.jpg" width="298" /></a></div>
<div style="text-align: center;">
Cutting my first parts on the laser cutter</div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPA-HZv4V3SXi8mbn064_5v-WNPJTQz8lSNoqRspHD67IatLG001eo1Cy9q3ei9sjNBez0Bi7qajaUoiiQvdfOa2usScxS7WbbY-bIECfCp78kGbMVf5pG2G5a3HN8V0VTWiLFWG7qgzs/s1600/IMG_2242.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPA-HZv4V3SXi8mbn064_5v-WNPJTQz8lSNoqRspHD67IatLG001eo1Cy9q3ei9sjNBez0Bi7qajaUoiiQvdfOa2usScxS7WbbY-bIECfCp78kGbMVf5pG2G5a3HN8V0VTWiLFWG7qgzs/s400/IMG_2242.jpg" width="400" /></a></div>
<div style="text-align: center;">
My assembled servo mount</div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU9E4oznCIb3VX6WJxN_qkPalW-j3gA0nuB4SV6tgcubfCV-W_mG4LfZmdrggwykk8SIpftpXXhf42SuS8Zmd1fSKSkcd9w6XXHvTKcfBg5nhyWTb6LnY5MQl1h3fras5jQIBnPU7_a58/s1600/IMG_2243.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU9E4oznCIb3VX6WJxN_qkPalW-j3gA0nuB4SV6tgcubfCV-W_mG4LfZmdrggwykk8SIpftpXXhf42SuS8Zmd1fSKSkcd9w6XXHvTKcfBg5nhyWTb6LnY5MQl1h3fras5jQIBnPU7_a58/s640/IMG_2243.jpg" width="480" /></a></div>
<div style="text-align: center;">
The servo fitting snugly in the mount</div>
<br />
Next I cut the parts for a steering leg, and while they went together without any difficulty, there was a lot of play in the plate holding the motor. I started to think about the tolerance of the parts I was cutting and I soon had a lot of questions which I needed to learn the answers to. I had modelled my parts in CAD software to the exact dimensions I wanted them. But clearly when you cut them out with any sort of tool some material is removed by the cutter (in my case vapourised by a laser, but the same applies to a saw where some material is removed by the blade). Thanks to the maker community on Twitter I learned that the width of the cut produced by a tool is called the 'kerf'. Once I knew that I was able to search online and learn about offsetting (adjusting for the kerf). If I modelled a part to be 30mm wide then the drawing output from my CAD program defined a part which was 30mm wide. But when I cut this on the laser cutter the resulting part was only around 29.8mm wide due to the kerf. This was not so significant for how the part looked, but my tab and slot fittings were just a little loose fitting due to this.<br />
<br />
There appeared to be 3 approaches people suggested:<br />
<ol>
<li>Specify an offset in the CAD program.</li>
<li>Offset my drawings in a 2D drawing program after exporting them from the CAD drawings.</li>
<li>Specify offsets in the laser cutter software.</li>
</ol>
<div>
I also realised that I needed to consider the sizes of holes for my various bolts and screws. I had used a 3mm hole size for an M3 bolt in the CAD software. But if I wanted a freely rotating M3 bolt without excessive wobble then 3mm was not quite right. The hole needs to be slightly larger than 3mm, but the kerf will mean a 3mm circle will be cut slightly larger. So what size circle does the laser cutter need to be given to get a hole just the right amount larger than 3mm for the bolt to fit freely but not too loosely? I also discovered that the offset features in some CAD software were not present in SolidWorks. I think this may be because while a hobbyist might be happy to apply offsets to their drawings where they are cutting parts themselves, a professional using a 3rd party to do their cutting does not know the kerf settings of the cutter to be used, so they leave it to the cutter operator to apply.</div>
<div>
<br /></div>
<div>
So for me there was no option 1. At the time I did not know whether option 3 was possible in the software on the MakeSpace laser cutters either. So I went for option 2, applying my offsets in a 2D drawing program. Various articles online pointed to using an offset feature in Adobe Illustrator. But I did not want to buy an expensive 2D drawing program when free alternatives were available. My go-to free 2D drawing program is Inkscape. This has a feature on the Path menu to Outset or Inset a shape. But this appears to apply a hard coded offset amount and distorted the shape of my parts adding curves to angled corners.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPdt-urXrZ75VNuQKqant6N0ecIzIcE7WL_O4daNGIKlH3MtT_LaQOKUJFSVgQKDOazk9GWYEzPwT7lK6bywtZrNtF4E1ulRHRr4Lwa-BqWXwBX8v0OhH0UaKfYdoz3CWmiIP9cvhYdAI/s1600/Offsets_Inkscape_Outset-Inset.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="752" data-original-width="1394" height="344" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPdt-urXrZ75VNuQKqant6N0ecIzIcE7WL_O4daNGIKlH3MtT_LaQOKUJFSVgQKDOazk9GWYEzPwT7lK6bywtZrNtF4E1ulRHRr4Lwa-BqWXwBX8v0OhH0UaKfYdoz3CWmiIP9cvhYdAI/s640/Offsets_Inkscape_Outset-Inset.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
A part with lines outset/inset using Inkscape</div>
<div class="separator" style="clear: both; text-align: center;">
(original outline in black, outset/inset lines shown in red)</div>
<div class="separator" style="clear: both; text-align: center;">
(the largest circle on the right side is 6mm diameter)</div>
<br />
Inkscape also has a feature called Dynamic Offsets where if you select just a single outline and then choose the Dynamic Offset option on the path menu (or Ctrl+J) then you get a drag handle and can adjust the line offset by hand. By duplicating each line I could manually offset it by approximately the line width (setting the line widths to the amount I wanted to offset them. There was still a little distortion of the shapes, but these were insignificant for the amount of offset I needed.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5k0JezcziYyAYjmm2Jb3sIN6CvlsjArcWAL3GDXTYZamDkLFTD85XG3ykC4u8t52AsdFmHqNzHnXiYH1uAb-TjE4411hczMiHVP-JN9HH2DzdzC9vfLKwcthkS2YYSLa1MSJvlr7QwBk/s1600/Offsets_Inkscape_DynamicOffset.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="752" data-original-width="1394" height="344" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5k0JezcziYyAYjmm2Jb3sIN6CvlsjArcWAL3GDXTYZamDkLFTD85XG3ykC4u8t52AsdFmHqNzHnXiYH1uAb-TjE4411hczMiHVP-JN9HH2DzdzC9vfLKwcthkS2YYSLa1MSJvlr7QwBk/s640/Offsets_Inkscape_DynamicOffset.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
A part with dynamic offsets applied by hand in Inkscape</div>
<div class="separator" style="clear: both; text-align: center;">
(original outline in black, offset lines shown in red)</div>
<br />
This enabled me to explore different amounts of offset and cut some parts to see what amount of adjustment gave me the right fit. But having to adjust every shape by hand dynamically was time consuming. It also made me realise that I needed different offset settings for different aspects of my parts. My 6mm shoulder bolts used in various pivots between parts needed a different amount of adjustment of the hole size than the machine screws holding parts in fixed positions, which was different to the slots cut to take tabs on the edges of other parts.<br />
<br />
I think perhaps option 3 (specify offsets in the laser cutter software) is preferable in the long run, but would require me to adjust all my hole sizes to include some aspect of hole size adjustment. (If I want a 6mm shoulder bolt to rotate freely then I want a slightly larger hole size than 6mm. I should model that hole size in CAD so that when I apply an offset for kerf in the laser cutting software the resulting hole is cut to exactly the size I modelled in the CAD software). At this point I asked a friend at work how SolidWorks recommend doing this, and he pointed me to the free version of DraftSight, as 2D drawing program from Dassault Systemes (who also own SolidWorks). Draftsight features an offset feature which allows you to specify the offset amount numerically. So I developed a workflow to manually apply offsets of different amounts to my various drawing parts using DraftSight.</div>
<div>
<br /></div>
<div>
I discovered that importing DXF files into DraftSight resulted in curves being converted into short sections of straight lines. So my nice rounded edges became jagged. This was avoided by exporting the drawings from SolidWorks as DWG format files. These can be read by DraftSight without converting the curves. I then had to weld all the line segments back together into single outlines for each part in DraftSight. Then I could apply a single offset to the entire outline of each shape (rather than to each line segment individually). Finally I exported the drawing in DXF format to take the file into Inkscape.</div>
<div>
<br /></div>
<div>
At this stage all my shapes have two lines for each feature of a part. The actual CAD drawing outline and the offset outline I want the laser to cut along. In Inkscape I coloured these cutting lines red, leaving the original lines black. That way I could easily verify which offset I have applied and that it is on the correct side (outside for the outlines of parts, and inside for cut-outs/holes in the part). The final step was to save the coloured drawing with offset lines in DXF format and import this into the laser cutter software, telling it to not cut the black lines, and applying cutting settings to the red lines. I was also able to add text to engrave into the material in Inkscape in a 3rd colour if needed and apply settings in the laser cutting software to engrave the shapes outlined by lines in that colour.</div>
<div>
<br /></div>
<div>
At last I was able to cut out parts on the laser cutter which were exactly what I had designed in my CAD model, and start to build my robot.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJacsKlU2mHPOe26a7SRCZEWltXqdlokdILMJSsVW3OW6HydGyzZXl2VImhQyjsZu94OjxQ7gxFhAuFtX2IosqHcuUp43qrgOIfF42AOtnYsvvxAI0ezxg7-U35wcTSDM4TAwWg2N6j7E/s1600/IMG_2265.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJacsKlU2mHPOe26a7SRCZEWltXqdlokdILMJSsVW3OW6HydGyzZXl2VImhQyjsZu94OjxQ7gxFhAuFtX2IosqHcuUp43qrgOIfF42AOtnYsvvxAI0ezxg7-U35wcTSDM4TAwWg2N6j7E/s400/IMG_2265.jpg" width="300" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
A set of parts for a steering leg</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFyUV2lHcNXDacPZE3OsSCzqmSbi8opkTY1RdY_oE947GPcy4vqVpTSu8sVNmRbgwyy7MB68QccvCgalTjvD3LRviFhM8c8Fl3JZG1wc4AnUl1eWeLQqp6KLUL_tt-0B0_nUvWsaZrXTw/s1600/IMG_2266.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFyUV2lHcNXDacPZE3OsSCzqmSbi8opkTY1RdY_oE947GPcy4vqVpTSu8sVNmRbgwyy7MB68QccvCgalTjvD3LRviFhM8c8Fl3JZG1wc4AnUl1eWeLQqp6KLUL_tt-0B0_nUvWsaZrXTw/s400/IMG_2266.jpg" width="300" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
An assembled steering leg with details of </div>
<div class="separator" style="clear: both; text-align: center;">
the kerf offsets used engraved onto the parts</div>
<br />Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com1tag:blogger.com,1999:blog-3131866441334625691.post-67601883149386277842018-11-30T06:11:00.000-08:002018-11-30T06:11:12.934-08:00Designing a Rocker Bogie Raspberry Pi RoverWhen the <a href="https://piwars.org/" target="_blank">Pi Wars</a> robotics competition announced the 2019 event with a space theme, it was clear that the various NASA mars rovers would be a source of inspiration for many potential competitors. I saw a few mentions of Rocker Bogie suspension on Twitter in connection with the competition. I had not heard this term before so I looked it up online. Wikipedia had an <a href="https://en.wikipedia.org/wiki/Rocker-bogie" target="_blank">article </a>with an animated graphic which had a caption saying it was not actually correct. I was intrigued, but still not sure what it was. I had my balance bot idea and felt that submitting an entry which was just saying I would build a mars rover inspired robot probably wouldn't make the cut for Pi Wars 2019. So I dismissed the idea at the time.<br />
<br />
What changed my mind was the publication by JPL of an <a href="https://opensourcerover.jpl.nasa.gov/" target="_blank">open source educational model</a> of the Mars Curiosity rover with full build instructions. Their website has a nice animation of their model rover which shows how the rocker bogie suspension really works using a differential pivot (link above: click on the rover to switch to the engineering model and then click the hotspots on the model). It looked like a really interesting build, and felt more likely to succeed in the Pi Wars competition than my balance bot idea. So I based my application on the idea of shrinking the design down to fit within the Pi Wars competition limit stated in the rules.<br />
<br />
In the month leading up to the submission deadline, I had started to learn CAD software for the first time. By the entry deadline I had modelled a steering leg from parts which could be cut from 3mm acrylic sheet.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj53zzfS0S0LEpCO49BMZkGNOGsC-OkmaxwOm-Uo-LW6Uhr8TL-Tr2BllCReoNSkPr0tN52YRVajobPVAQmCnbbjHid9EDZRHSIzHynuBwmc6uQW-2xgRMKGRA81fUPRMY0viUFIlP7OhM/s1600/PiWarsSteeringLeg.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="782" data-original-width="470" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj53zzfS0S0LEpCO49BMZkGNOGsC-OkmaxwOm-Uo-LW6Uhr8TL-Tr2BllCReoNSkPr0tN52YRVajobPVAQmCnbbjHid9EDZRHSIzHynuBwmc6uQW-2xgRMKGRA81fUPRMY0viUFIlP7OhM/s400/PiWarsSteeringLeg.jpg" width="240" /></a></div>
<br />
I included this picture in my application. This is what I wrote on my application form:<br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif;"><i>My plan is to design and build a 6 wheel drive rover with full rocker-bogie suspension. The design should be able to turn on the spot, and drive over uneven terrain while keeping all 6 motor driven wheels in contact with the terrain.</i></span><br />
<i><br /></i>
<span style="font-family: Arial, Helvetica, sans-serif;"><i>I have seen that the most common good performing design for a Pi Wars robot is a standard 4 wheel drive rectangular chassis, but I saw so many of them at the event last year I felt there should be more variety. So I was looking for ideas for something that would be more visually and mechanically interesting. After several months of trying to build a 2 wheeled balancing robot, I have learned a great deal, but also realised this is probably too big a step for my first entry attempt. I’ll never have the time to learn all the computer vision and autonomous driving code if I stick with that plan. So I decided to embrace the Space Exploration theme. After discovering the JPL Mars Rover open source design I am working on designing a scaled down A4 footprint version which I plan to build from acrylic, using the micrometal gear motors and moon buggy wheels as used on the Coretec Robotics Tiny 4WD robots. My aim is to build something visually exciting and mechanically interesting using affordable components. Other components I have bought (but not learned how to use yet!) include a PixyCam2, and a brushless motor and ESC with a view to build a Nerf dart firing mechanism.</i></span><br />
<br />
<br />
To my delight I got a place in the 2019 competition. Now I had a lot of learning to do. I joined Cambridge <a href="http://makespace.org/" target="_blank">Makespace </a>in order to learn how to use a laser cutter and start working on turning this idea into reality.Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-18260346455137028982018-11-23T05:39:00.000-08:002018-11-23T05:39:31.028-08:00Self Balancing Robot - Part 2<br />
In my <a href="https://adventures-with-pi.blogspot.com/2018/10/self-balancing-robot-steep-learning.html" target="_blank">previous post</a> I described the problems my initial attempt at coding a balance bot ran into. Specifically the vibrations or shockwaves from the motors turning on and off swamp the accelerometer readings in noise. So instead of measuring the direction of gravity acting on my robot, the accelerometer is measuring the accerleration forces of these shock waves through the chassis. The robot just vibrated noisily and fell over because I could not measure angle of tilt of the chassis this way. Then it shot off across the room lying down. This second aspect was more concerning initially as it risked damaging my robot. So I dealt with that first.<br />
<br />
Once the robot had toppled over, the motors are not able to right it again. There is an angle of tilt beyond which gravity wins over the power of the motors I have. At less steep angles of tilt the robot tries to drive at speed across the room, attempting to get the wheels back underneath the centre of gravity of the robot. I did not know exactly what angle the robot was unable to recover balance beyond, so I just picked 45 degrees from vertical as a starting point (I can tune this value later when I have the fundamentals working). If the robot was tilted at an angle of over 45 degrees from upright, then I set the code to keep the motors off. That way the drive is automatically off if the robots is lying down, and turns off pretty quickly when it falls over.<br />
<br />
Now I just needed to work out how to effectively measure the angle of tilt using the IMU when the motor vibrations mask this information read from the accelerometers alone. My IMU is a 9dof chip (that's 9 degrees of freedom). These come from 3 sets of sensors each of which is measuring along 3 orthogonal vectors (x, y and z axes). We've already talked about the accelerometer (measuring changes in directional forces acting on the chip). The other 2 types of sensor are magnetic field strength, and gyroscopic. The gyros measure the rate of rotation around each axis. If we know how fast something is rotating and we measure this for a short enough time interval (so that the reading we take represents the average over the whole time period) then we can work out how many degrees we have rotated during that time. This allows us to work out the change in tilt angle of our robot since we last knew the angle of tilt, so we can update the angle in our code.<br />
<br />
I found example code doing this where the time interval was stored in a constant for their program, based on how long their code loop took between readings. But this appeared flawed to me as what if the code in my loop varied in how long it took to run? So instead I just captured the time just after taking a reading, and then on the next reading I could work out how long had elapsed since the last reading. If you mount your IMU chip so that one of the 3 axes is parallel to the axle of your balance bot wheels then you only need to read one of the 3 axes of the IMU gyros. So with this code we can determine how much our robot tilt angle has changed in the last loop cycle. To work out the actual angle of tilt we also need to know what angle we started at. The gyros cannot tell us this, so we need to use the angle calculated from the accelerometers first. This is OK as long as we read this when the robot motors are off and the robots is not being knocked about. The perfect time is when the robot is being tilted upright to start with, or it is lying down with the motors off not moving at all.<br />
<br />
My code design so far is structured as follows.<br />
<br />
<ol>
<li>The loop is timed at the start. This means the first time around the loop the calculated time elapsed will be wrong, but we don't use it on the first pass round the loop so that does not matter. By the time we start reading the gyro we will know now long we have been in the loop. </li>
<li>We start in accelerometer mode, and stay in that mode until we get stable tilt readings. This ensures we know the true tilt angle read from the accelerometers while the robot is stationary.</li>
<li>Once we know the tilt we can switch to gyro mode. By this time we have been round the loop more than once, so the time elasped calculation is correct for the current loop iteration. We use it to work our how much we rotated according to the gyros in that time.</li>
<li>We add/subtract the amount of rotation since the previous loop iteration from the tilt angle we last calculated, to update it to the new tilt angle.</li>
</ol>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Initialise:</span></div>
<span style="font-family: "courier new", courier, monospace;"> Set measure mode to Accelerometers</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Initialise last loop time to zero</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">Loop:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Get the time now</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Calculate the time elapsed since last loop iteration</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (time_now - last_loop_time)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Update last_loop_time = time_now</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> If Measure mode is Accelerometers:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Calculate angle of tilt measured from the accelerometers</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> If angle is very close to last measured angle:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Switch measure mode to Gyros</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> Else (measure mode is gyros)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Read rate of rotation around axis of wheels (using the gyro)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><span style="font-family: "courier new" , "courier" , monospace;">Calculate how far we rotated since last tilt calc</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (degrees rotated per second * seconds elapsed)</span><br />
<br />
The psuedo-code above hopefully explains the basic approach, but there is a problem with it. Once we switch to gyro mode, we only ever calculate tilt based on the previously calculated tilt. So any inaccuracy in the measurements can result in the calculated value drifting from the actual tilt angle. Only a small amount of drift will cause the robot to try to maintain an angle different to the perfect balancing angle, and the only way to keep that angle is to keep moving. So the robot will quickly start to head off at speed across the room. Now we are driving the motors we cannot rely on a precise reading from the accelerometers, so how do we correct for this drift in the gyro calculated reading?<br />
<br />
I get a lot of help from fellow makers on Twitter, and in this case extra credit must go to <a class="pretty-link js-user-profile-link js-nav" data-user-id="2313264175" href="https://twitter.com/PiTutorials" style="background: rgb(255, 255, 255); color: #2fc2ef; font-family: "segoe ui", arial, sans-serif; font-size: 14px;"><strong class="fullname" style="color: #14171a; word-break: break-all;">Keith's Pi Tutorials</strong></a> for pointing me at the following resources. The problem of determining when something is level against the background vibration of motors is the same for autoleveling flying drones like quadcopters. Keith pointed me to the following website <a href="http://www.brokking.net/yabr_main.html">http://www.brokking.net/yabr_main.html</a> which in turn links to a couple of tutorial videos on YouTube on autoleveling quadcopters. The first video is here and links to part 2 in the comments:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/4BoIE8YQwM8/0.jpg" src="https://www.youtube.com/embed/4BoIE8YQwM8?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br />
<br />
After thinking and playing with these ideas I realised that while the quadcopter example is having to level in 2 directions (pitch and roll), our balance bot case is much simpler. We only need to consider one axis of rotation, the axis of our wheels axle. Our robot only needs to rotate around this one axis to self balance. The technique in summary is to mix a small amount of the tilt angle calculated from the accelerometers alone with the tilt angle calculated from the gyros. The accelerometer calculated tilt values are very noisy, but over time their average represents the constant force of gravity. So mixing in a very small amount (~0.05%) to the gyro readings does not throw off the calculated tilt significantly, but it is enough to correct for the drift in the gyro readings over time.<br />
<br />
With this knowledge I was able to get some initial code working which gave me a reliable tilt angle whether the motors were on or off. I was able to start experimenting with PID tuning next, but that will have to be another post. What I had realised was that this was going to take me too long to perfect for my first Pi Wars competition entry, and another idea had come along which looked much more suitable for my submission for a place in the 2019 competition. We'll look at this in my next post.<br />
<br />Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-33855333917288537262018-10-06T09:32:00.001-07:002018-10-21T05:56:07.897-07:00Self Balancing Robot - A steep learning curve!I've always wanted to build a self balancing robot, and I thought it would make a very visually interesting Pi Wars competition entry. Some searching online and some pointers from members of the maker community on Twitter led me to a number of projects on YouTube with links to blog articles and code. But all these examples seemed to be of the 'recipe' format. By this I mean they contained detailed instructions to build the exact same robot as the author, using the same parts. Then just deploy the provided code (mostly onto an Arduino) and VOILA! A self balancing robot. If only things were that simple.<br />
<br />
I didn't just want to build someone else's project. I wanted to understand how it actually worked, and build my own robot using the components I had. I wanted to understand the theory and the code so I could design my own. So I started to dig deeper into one of the examples. I learned that the feedback from a tilt sensor is generally processed by a PID algorithm to control the power and direction of the motors to try and maintain an upright position for the robot. It all sounded simple in principle. Use a sensor to measure the angle of tilt, feed this value along with the desired angle of tilt into a PID controller library and apply the output to the motor drivers.<br />
<br />
<h3>
So what is PID?</h3>
Before you Google it and find the page on Pelvic Inflamatory Disease, we are talking about a PID Controller, or Proportional Integral Derivative controller. You might find the <a href="https://en.wikipedia.org/wiki/PID_controller" target="_blank">Wikipedia page</a> of interest. There is a PID controller library available for Arduino, and the author Brett Beauregard has written a series of very detailed <a href="http://brettbeauregard.com/blog/category/pid/" target="_blank">blog articles</a> about the theory. Here I will just talk about the usage of his library for a balance bot. In simple terms, you keep reading the angle of tilt between your robot and the force of gravity. On each loop through your code you feed in this measured angle, and the PID Controller calculates a power value to apply to the motors to bring this angle closer to the desired angle. For a stationary balancing robot, we want the robot to be upright and the motors off. If the robot is starting to topple over then the angle moves away from this desired upright angle and power is applied to the motors to restore balance. The greater the difference between the actual measured angle and the desired 'upright' angle, the more power is needed to allow the motors to restore balance. But too much power and the robot is tilted over the other way. So the PID controller constantly needs updating with the current tilt, and needs to apply a new correction to the motors.<br />
<br />
The PID Controller also takes 3 input values which control the output for different changes in input over time, and these need to be tuned to make a stable robot. These tuning constants are referred to as Kp, Ki, and Kd. I was pointed to <a href="https://www.youtube.com/watch?v=uyHdyF0_BFo" target="_blank">this video</a> which demonstrates the effects of different values for these constants.<br />
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allow="autoplay; encrypted-media" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/uyHdyF0_BFo?rel=0" width="560"></iframe><br /></div>
<div style="text-align: center;">
<br /></div>
Most of the example code I came across supplied values for all 3 constants. But I learned that these values depend on the physical characteristics of your robot. How heavy is it, and how the weight is distributed. How fast your motors are and how much torque they generate. So there are no 'magic values' you can just use. You need to tune your own robot once you have built it. So we had better look at what I actually built.<br />
<br />
<h3>
A Self Balancing Robot Development Board</h3>
To prototype and build a proof of concept you don't need a bunch of fancy machinery and a workshop. I started with a sheet of plywood from my local DIY store, a hand saw and the patio table in the garden as a workbench (so I didn't need to sweep up my mess!).<br />
<br />
In my parts boxes, I already had the following:<br />
<br />
<ul>
<li>An Arduino UNO.</li>
<li>A pair of Adafruit motor driver breakout boards.</li>
<li>A set of PiBorg motors and wheels.</li>
<li>A Sparkfun 9dof IMU breakout board</li>
</ul>
<br />
I had no idea what sort of motors I needed so I took the approach of just trying out what I had to hand first, before going out and buying something I possibly didn't need. Here is what I built.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsbwyFGE5lTJV3ab-rcJujc5mUenCeCbAz2Tbc_xzhEDKSBk4RDTZipNSURVL3-kCZ_QprTD8eHt8e8Nbq2xwF8YDO1qK40ky2rQvKqbT-EipnEvbxhFKHUN5feNua6dQXUHWss99J7BY/s1600/IMG_E2045.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="638" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsbwyFGE5lTJV3ab-rcJujc5mUenCeCbAz2Tbc_xzhEDKSBk4RDTZipNSURVL3-kCZ_QprTD8eHt8e8Nbq2xwF8YDO1qK40ky2rQvKqbT-EipnEvbxhFKHUN5feNua6dQXUHWss99J7BY/s400/IMG_E2045.jpg" width="318" /></a></div>
<br />
I simply cut a rectangle of plywood, and bolted everything on. I used cable ties to hold the batteries in place. The physical build did not take long at all. You can use any motor driver boards which can handle the stall current of your motors (this is now much current the motors will draw if they are powered but are prevented from turning). I used the example code from the IMU board I had to read the angle of tilt from vertical using the accelerometers. In my case, the angle was 180 degrees when the robot was balancing upright. Using this information I just needed to use the PID library to calculate the motor power needed to maintain balance, in a loop so it constantly updates based on any change in the tilt value. I am not going to give the full code here, but instead try to explain the principles I was using. We'll look at some actual fully working code in a follow up post.<br />
<br />
The PID Controller takes the following inputs:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);</span><br />
<br />
The variable names with & in front indicate these are pointers to the variables in my Arduino program. So any changes made to their values anywhere in my program will be available to the PID controller code. I wanted my robot to maintain a tilt of 180 degrees, so my setpoint value was 180. Kp, Ki and Kd are the tuning constants I needed to set to appropriate values for my robot. Input is the value of tilt I was reading from my accelerometer, and output is the power and direction I needed to run my motors. The PID library needs to know the range of values I want my output to range between, so I also had to setup the PID controller with this information:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> pid.SetOutputLimits(-100, 100); </span><br />
<div>
<br /></div>
<div>
So now the PID controller knows my motor output values need to be in the range -100 (full power reverse) and +100 (full power forwards). In the main program loop, I now just needed to read the tilt from the IMU, run the PID Controller calculation, and apply the output power to my motors. Or so I thought. It turns out there are a number of complications I had not taken into account (and which the example project I was trying to follow did not use). What actually happened when I turned it on was that my robot just vibrated very loudly and fell over. Then once it hit the floor it shot off across the room with the top of the board scraping along the floor!</div>
<div>
<br /></div>
<div>
It turned out that the motors were put into full power forwards, which generated a shock to the IMU making the accelerometer read a very high value. This cause the PID controller to put the motors into full reverse, causing an opposite direction shock to the board. This repeated on every iteration of the loop. So the motors alternated between fast forward and fast reverse. The whole thing was shaking, causing the buzzing sound and the tilt values being calculated were not related to the angle of tilt of my robot at all, but to how hard it was being shaken by the motors.</div>
<div>
<br /></div>
<div>
At the time I did not understand what was wrong, so I posted my failure on Twitter:</div>
<div>
<div style="text-align: center;">
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
Finished my first <a href="https://twitter.com/hashtag/PiWars?src=hash&ref_src=twsrc%5Etfw">#PiWars</a> hardware test platform and wrote Arduino code for balancing. It completely fails to work! Vibrations from the powerful motors changing direction shakes the accelerometer so much it cannot provide useful angle of tilt data. It just shakes violently. <a href="https://t.co/4WL7ZynsL8">pic.twitter.com/4WL7ZynsL8</a></div>
— Dr Footleg (@drfootleg) <a href="https://twitter.com/drfootleg/status/1028732054308089857?ref_src=twsrc%5Etfw">August 12, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
</div>
<div>
Pretty quickly got some great pointers to more information. Clearly I had more reading to do. In my next blog post I will explain how these problems in my initial design were solved.</div>
<br />
<br />
<br />
<br />
<br /></div>
Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-60371832724521683902018-09-03T05:17:00.001-07:002018-09-03T05:24:15.431-07:00Mentoring School Teams for Pi WarsAs I already lead a code club and volunteer at youth groups to give Raspberry Pi and robotics workshops, it makes sense for me to get involved with mentoring school team entries for Pi Wars. This may prove to be a distraction from my own plans for a Pi Wars entry, but I expect it will actually focus my thinking on design and building robots. I am sure it will also expose me to a great level of creativity and ideas which will benefit my own entry. My daughter was inspired to enter the Pi Wars 2019 competition after attending the 2018 competition as a spectator, and originally the plan was to encourage her to put in an individual entry. But then she got one of her school friends interested and I had two children wanting to work on an entry. So I contacted their school computing teacher to see if they were interested in running a school team entry (or multiple teams). Their teacher was very interested in the idea, and I am now tasked with preparing and giving a school assembly on Pi Wars early in the new school year (with around 20 days remaining to get entries in).<br />
<br />
Over the school Summer holidays I have been working with my daughter to guide her and her friend to start building a robot chassis and writing some Python code. We chose Lego Technic and a tracked tank like design. This enables rapid prototyping and learning a lot about the mechanics of building a working tank chassis.<br />
<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
A highly successful evening coding her <a href="https://twitter.com/hashtag/PiWars?src=hash&ref_src=twsrc%5Etfw">#PiWars</a> robot. We hacked the holiday cottage, borrowing the DVD player HDMI cable to use the TV as a screen to debug network issues & borrowed the AAA batteries from 2 remote controls for the <a href="https://twitter.com/ThePiHut?ref_src=twsrc%5Etfw">@ThePiHut</a> game controller. <a href="https://t.co/qbMSci0o5q">pic.twitter.com/qbMSci0o5q</a></div>
— Dr Footleg (@drfootleg) <a href="https://twitter.com/drfootleg/status/1026941138526236675?ref_src=twsrc%5Etfw">August 7, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
We had a lot of fun building the chassis over the holidays, and took it all away with us to work on while on our Summer family holiday.<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
We created a state table for the controller joystick positions and what the motors should be doing for each combination. Then wrote some pseudo code encode the design ready to convert to Python for her <a href="https://twitter.com/hashtag/PiWars?src=hash&ref_src=twsrc%5Etfw">#PiWars</a> robot. <a href="https://twitter.com/hashtag/STEM?src=hash&ref_src=twsrc%5Etfw">#STEM</a> <a href="https://twitter.com/hashtag/GirlsInStem?src=hash&ref_src=twsrc%5Etfw">#GirlsInStem</a> <a href="https://t.co/eibix6lOcF">pic.twitter.com/eibix6lOcF</a></div>
— Dr Footleg (@drfootleg) <a href="https://twitter.com/drfootleg/status/1027536107972513793?ref_src=twsrc%5Etfw">August 9, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
We used a state table to design what she wanted the motor control code to do in response to different positions of controls on a game controller. This was a great success in coaching her to create a design, and then realising that design in code. My daughter was really engaged with the project and it has kindled a desire in her to learn Python. After the holiday we visited our local library and she picked out two childrens 'Learn Python' books which she has started to work through at home. A very successful start and a great example of how a project like a Pi Wars entry generates the drive to learn new skills and overcome challenges.<br />
<br />
Now I need to overcome the challenge of giving an assembly at my daughter's school to inspire other children to enter the competition this year.<br />
<div>
<br /></div>
Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-58133304900673223162018-07-13T05:45:00.000-07:002018-07-13T05:45:53.844-07:00Ideas for My First Pi Wars RobotOne of the things I noticed at Pi Wars 2018 was that there were a lot of very similar robot designs as far as the basic chassis, drive and steering are concerned. Four wheel drive, fixed mount wheels on a rectangular chassis, with steering done by reversing the direction of the wheels on one side compared to the other. Clearly a winning formula and very effective on the more challenging terrain of the obstacle course.<br />
<br />
A great source of ideas and knowledge are the blogs written by previous entrants (check out the <a href="https://piwars.org/2018-competition/pi-wars-2018-blogs/" target="_blank">Pi Wars 2018 blogs</a> or others on the 'past years' pages of the <a href="https://piwars.org/" target="_blank">PiWars.org</a> website). There were a few rather different entries, many of which really struggled in the challenges. But it was these that I enjoyed watching the most. Some tracked tank like designs worked well and one <a href="https://twitter.com/davejavupride/status/956258791456149504" target="_blank">omni-wheeled robot</a> had some awesome moves.
<br />
<br />
I am not so much motivated to try to win the competition, as to entertain and inspire. Sure I want to design something that performs well, but not at the expense of individuality. So I came away from the 2018 competition thinking it would be cool to enter something completely different. I had always liked the idea of building a 2 wheeled balancing robot, so my plan was to try and build one capable enough to tackle the challenges at Pi Wars. It turned out I was not alone!<br />
<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
Started building my <a href="https://twitter.com/hashtag/PiWars?src=hash&ref_src=twsrc%5Etfw">#PiWars</a> 2019 robot protype chassis, 2U-2M3 <a href="https://t.co/diwjttATEQ">pic.twitter.com/diwjttATEQ</a></div>
— Brian Corteil 🤖 (@CannonFodder) <a href="https://twitter.com/CannonFodder/status/1013901881742065664?ref_src=twsrc%5Etfw">July 2, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<br />
So the learning phase begins. Here are some of the questions I have at the start:<br />
<br />
<ul>
<li>What sort of motors are needed for a balancing robot?</li>
<li>How do you use an accelerometer sensor?</li>
<li>How do you control a pair of motors using the tilt sensor data to keep it balanced?</li>
<li>How do you get a balancing robot to move forwards and backwards while the motors are being driven to keep it balanced upright?</li>
<li>How big can a 2 wheeled balancing robot be and still qualify for the Pi Wars rules of maximum size?</li>
<li>Is this idea completely mad?</li>
</ul>
<div>
I decided to start experimenting with the parts I already had in my boxes of bits I've bought already for robot projects in general. A pair of motors from <a href="https://www.modmypi.com/motors-mounts-and-wheels-1140/12v-300-rpm-monsterborg-motor-p37uk12/" target="_blank">PiBorg</a>, a <a href="https://shop.pimoroni.com/products/sparkfun-9dof-sensor-stick" target="_blank">SparkFun 9dof sensor</a> breakout board, and some <a href="https://shop.pimoroni.com/products/adafruit-drv8871-dc-motor-driver-breakout-board-3-6a-max" target="_blank">AdaFruit 3.6A motor driver</a> breakout boards. It seems like a good idea to use a dedicated processor to handle the sensor reading, balancing and motor driving aspect of things. I don't want the robot falling over every time the Raspberry Pi is busy doing something else when I start looking at image sensing and autonomous driving challenges. So I started with an Arduino board to attempt to build my first prototype.</div>
<div>
<br /></div>
<div>
This added a couple more questions to my list of things I needed to learn:</div>
<div>
<ul>
<li>How do you program an Arduino?</li>
<li>How do you communicate between an Arduino and a Raspberry Pi?</li>
</ul>
<div>
This is going to be a very educational journey!</div>
</div>
Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-22946855915336928452018-07-12T13:52:00.000-07:002018-09-03T04:48:28.827-07:00The Beginning of My Pi Wars JourneyBack in September 2017 as I was starting to engage with people in the Raspberry Pi community on social media, a friend told me I would love Pi Wars and should check it out. A quick Google search brought me to <a href="https://piwars.org/" target="_blank">PiWars.org</a> where I learned about this exciting non-destructive robotics competition in Cambridge. Unfortunately the deadline for entries was only about 3 weeks away, and I had only just built my first robot using the <a href="https://adventures-with-pi.blogspot.com/2017/08/building-our-first-robot.html">CamJam Edukit #3</a> which started me on these adventures. Looking at the challenges it was clear I had a lot to learn before I could write an entry application. So it would not be for that year. I noted the date of the competition in my calendar and planned to attend.<br />
<br />
<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/AVvXsEjMVPvl6-w-x-f7bgPrgiux_TZ-BHoWRcCJV-8WDRDnCae1wJmaNy4EKASzf4v60pVARXCI5t_HVfcuFZ59ktsS_162gOIX0egeJhz3ERx522C9mD6qztvWdSeJWj_U9AwHneIC4gmR-qw/s1600/P1170556.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="749" data-original-width="1200" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMVPvl6-w-x-f7bgPrgiux_TZ-BHoWRcCJV-8WDRDnCae1wJmaNy4EKASzf4v60pVARXCI5t_HVfcuFZ59ktsS_162gOIX0egeJhz3ERx522C9mD6qztvWdSeJWj_U9AwHneIC4gmR-qw/s400/P1170556.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">It was a start, but I was going to need something a bit more sophisticated than this.</td></tr>
</tbody></table>
Over the next 6 months, I built my first few robots. Mainly as technology demonstrators for kids clubs and workshops I had been volunteering at. As the date of the Pi Wars competition approached, I went to a couple of the excellent meet ups at Cambridge Makespace organised by previous Pi Wars winner Brian Corteil where I got to meet some of the competitors and see some of their robots in development. I registered as a volunteer for the event and when the weekend of the competition came, I did the morning shift judging the obstacle course for the schools entries on the Saturday.<br />
<br />
As well as seeing lots of robots over the Pi Wars weekend, I also learned a lot about what went wrong for competitors. Robots which could not grip on slopes, or get over the edge of a piece of plywood. Batteries which came loose and dangled on the ends of their leads as the robots attempted the courses. Controllers which stopped talking to their robots. Robots which stopped when their software crashed each time they took a knock. Robots which arrived at their time slot for a challenge with the wrong version of the code on their SD Card. Operators who struggled with the fine control needed to get their robot to drive where they wanted when they wanted.<br />
<br />
Clearly a competition robot needed to be robust, well tested and the driver well practised in operating it. It also helped to have pink unicorn stickers on it (well it should look interesting, not just be functional). I took my kids along on the Sunday to spectate, met a lot of people, bought lots of parts to build bigger and better robots and came away with my daughter saying she wanted to enter, and wanting to have a go myself too.<br />
<br />
So now the Pi Wars 2019 dates have been confirmed, and the details of the challenges published. Clearly it is time to start thinking up some ideas!Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-13315085432247022252017-08-24T15:03:00.000-07:002017-08-24T15:03:15.462-07:00Building Our First RobotUsing the CamJam Robotics kit and a Raspberry Pi, the kids and I has started building our first programmable robot. As this was my first adventure with the Raspberry Pi, I kept the cost to a minimum and used a Pi Zero. If you are serious about getting into building and controlling hardware from a computer, I would really recommend starting with the full size Pi 3 model, as it will make setting up and prototyping experiments easier. You can read the post about my <a href="http://adventures-with-pi.blogspot.com/2017/04/recommended-raspberry-pi-3-starter-set.html">recommended Pi 3 set up</a> for my recommendations on what to buy if you want the fully featured Pi. If you decide to start out with the cheaper Pi Zero, then see my post about the challenges of <a href="http://adventures-with-pi.blogspot.com/2017/03/getting-started-with-raspberry-pi-zero.html">getting started with the Raspberry Pi Zero</a>.<br />
<br />
Here is a picture of the parts for our first robot:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFaDGGZjPkb6vygoiVuXLT5Bwwyziva34Fu0uzgoUEIPAJu0NeXJHo6VsDnxOWVr2egZmiwX-gbFFmPibcXW4weMfNGawPb0jaZtrB7nGZRg5mRRsfEK_1YK2hzXBDCqx1dggScstrNCc/s1600/P1110303.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="604" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFaDGGZjPkb6vygoiVuXLT5Bwwyziva34Fu0uzgoUEIPAJu0NeXJHo6VsDnxOWVr2egZmiwX-gbFFmPibcXW4weMfNGawPb0jaZtrB7nGZRg5mRRsfEK_1YK2hzXBDCqx1dggScstrNCc/s640/P1110303.jpg" width="640" /></a></div>
<br />
This is what you can see in the picture:<br />
<ul>
<li>USB Powerpack (portable battery to power the Pi)</li>
<li>Raspberry Pi zero (in a case)</li>
<li>USB Wifi dongle, and adapter to fit the mini USB port</li>
<li>CamJam Edukit #3: Robotics</li>
<li>4 x AA NiMH rechargable batteries</li>
<li>Micro SD card (8GB or larger)</li>
</ul>
<div>
In order to initially configure the Pi zero, you'll also need a keyboard which can be plugged into the single micro USB port on the Pi, and a mini HDMI to HDMI adapter plus an HDMI lead to connect a TV or monitor. Once you have it configured you can remove the keyboard and display, and connect remotely over the WiFi network from another computer. This allows you to program your robot without having it connected to anything by cables, so it can roam freely around the room (or anywhere within range of your WiFi network). In addition to connect the robot interface board from the CamJam kit, you will need a male 40 way header which you'll have to solder onto the Pi zero. See my post about on <a href="http://adventures-with-pi.blogspot.com/2017/03/getting-started-with-raspberry-pi-zero.html">getting started with the Raspberry Pi Zero</a> for full details of the initial set up. If you don't want to have to solder anything then you can build this same robot kit using a Pi 3 instead, which has both built in WiFi and the 40 way header already attached. (Since I wrote this, the Pi Zero W board has been released. This is like the Pi Zero but has Bluetooth and WiFi built in. You can also get a 'hammer in' header if you are not ready for soldering. See <a href="https://adventures-with-pi.blogspot.com/2017/03/links-scratchpad.html">supplier links</a> for details where to buy these).</div>
<div>
<br /></div>
<div>
After the initial set up of the Pi, you will have access to it from a computer over a wireless network and can start building the robotics kit. At this point I was able to get the kids involved, starting with opening the CamJam Edukit box to see what was inside. My children are aged 9 years (girl) and 6 years (boy). We built our robot using the box that the kit came in. The motors can be stuck onto the bottom of the box and the wires threaded through holes in the bottom of the box to attach to the interface board screw terminals. Then the Pi and the batteries can all go inside the box and it is ready to program and roam around the house. My children enjoyed sticking on the motors and threading the wires. I helped them connect it all up correctly. The worksheets for the CamJam kit (which you can <a href="https://camjam.me/?page_id=1035" target="_blank">download here</a>) walk you through all of this.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirWovgDPPeVXNNAoqpYRKrYaS45LL7msNGtkwJjQaeilVSEW7fbJdi_mNgJWrWIvJbeuCQL4MsCxbV6R3FPLE0IxZmPJ3YkqKN2GjphFXZqQZtJCAoCP3JWn92dNImK2dsZ8CeXc6MwB4/s1600/P1030068.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirWovgDPPeVXNNAoqpYRKrYaS45LL7msNGtkwJjQaeilVSEW7fbJdi_mNgJWrWIvJbeuCQL4MsCxbV6R3FPLE0IxZmPJ3YkqKN2GjphFXZqQZtJCAoCP3JWn92dNImK2dsZ8CeXc6MwB4/s640/P1030068.jpg" width="360" /></a></div>
<br />
<br />
The first step is to load a script to get the robot to simply move in a straight line. This is done by calibrating the scripts so that the motors run at the same speed. My children are not ready to be exposed to Python code yet, so I talked them through what we wanted to do, and asked them questions about how the robot was behaving as we calibrated the script. The code controls the motor speed by sending a pulse width modulated signal to the motors. This is a square wave and we are varying what percentage of the time the voltage is high compared to zero in the waveform. 100% high would be sending full power to the motors all the time. 50% high would send half the power, making the motors run at a slower speed. So we started with 50% and saw that the robot drove along a curved path. At this point I asked the kids why it was not going in a straight line, and nudged them towards the answer that one motor was running faster than the other. I got them to work out which one was going faster. We then reduced the power slightly to that motor and run the script again so see what happened. After a few attempts the kids understood the affect the code changes were having (without having to look at the code) and we had some values which made the robot run more or less in a straight line. I later found that this varied depending on the floor surface. So in the kitchen it behaved slightly differently than on the carpet in the living room.<br />
<br />
Next we looked at making the robot turn left and right, again asking the kids what directions we needed to drive the motors to make it turn. This made for a great first lesson for the kids, and a good introduction to programming in Python on the Pi for me. Away from the kids I then set about writing some functions to hide the lower level code so that we could look at some simple Python scripts calling functions to move the robot forward, and turn left or right. With these simpler scripts I was able to show my daughter some code and she could understand how to start to chain together commands to make the robot drive in a square around the kitchen on another day.</div>
Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-90741709737587347612017-07-11T06:08:00.002-07:002017-07-13T14:22:44.622-07:00Interfacing the Explorer HAT Pro with ScratchLooking for a way to get started with younger children in interfacing simple electronic circuits to the Raspberry Pi with Scratch, I learned that the Explorer HAT Pro from <a href="https://shop.pimoroni.com/products/explorer-hat">Pimoroni</a> is supported in Scratch. Once everything is set up and configured this provides a great beginners platform for driving LEDs, buzzers and motors from Scratch programs, and enabling sensors and inputs to be read from within Scratch. Perfect for little coders in my school code club and protecting the Pi from damage due to circuit design errors. But getting this working in the first place was not straight forward, so here is my guide to setting it all up and getting started with some Scratch examples.<br />
<br />
This post is very much a work in progress as I learn more and uncover new information. So I plan to regularly update it as I learn more. But I am publishing it now because I think it already brings together a lot of information that I have found was not easy to search for online.<br />
<br />
Scratch 1.4 (Nu Scratch) in Raspbian Jessie can control the built in LEDs, the 5V inputs and outputs, and the motor drivers on the Explorer HAT Pro. But it cannot detect the capacitive touch inputs. The HAT was also a bit temperamental in starting to work with Scratch. I had to open and run the example from Motors and Sensors first before it started behaving. I am not sure that example contains anything my template does not, or whether it just needed a project closing and reopening to sort it out. More testing needed. I started a Vanilla Scratch project template to show how to do everything. One problem is that the ways to switch on the outputs and LEDs do not all appear to work. I can switch LEDs on and off using variables, but not the outputs (which only appear to respond to broadcast messages).<br />
<br />
The instructions which cover how to use Scratch 1.4 with GPIO and various supported add on boards can be found here: <a href="https://www.raspberrypi.org/documentation/usage/scratch/gpio/README.md" target="_blank">https://www.raspberrypi.org/documentation/usage/scratch/gpio/README.md</a><br />
<br />
I have uploaded my first Scratch 1.4 template project if you are interested in using it:<br />
<a href="http://wscc.darkgem.com/footleg/codeclub/ExplorerHAT%20Vanilla%20template1.sb">ExplorerHAT Vanilla template1.sb</a><br />
<br />
The capacitive touch inputs are supported by Scratch GPIO Plus 8, which can be installed from:<br />
<a href="http://simplesi.net/scratchgpio/scratch-raspberrypi-gpio/" target="_blank">http://simplesi.net/scratchgpio/scratch-raspberrypi-gpio/</a><br />
<br />
This appears to use a slightly different approach to controlling things (setting specially named variables values to turn things on and off). I still need to experiment more to understand how they play together. Some examples can be seen here: <a href="http://simplesi.net/explorerhat/">http://simplesi.net/explorerhat/</a><br />
I had to reboot the Pi after installing Scratch GPIO in order to get them to work. I found it temperamental and did not work after I shut down Scratch and reopened it.<br />
<br />
Camera support is covered here: <a href="https://www.mattvenn.net/2014/12/16/using-a-camera-with-scratch-on-the-raspberry-pi/">https://www.mattvenn.net/2014/12/16/using-a-camera-with-scratch-on-the-raspberry-pi/</a><br />
<br />
Support for capacitive touch sensors is also covered in this article: <a href="http://www.pawfal.org/dave/blog/tag/scratch/" target="_blank">http://www.pawfal.org/dave/blog/tag/scratch/</a><br />
<br />
Worksheets from NI Raspberry Jam covering Scratch ExplorerHAT Pro here: <a href="https://github.com/NIRaspberryJam/Raspberry-Jam-Resources/blob/master/Sections/Explorer-HAT-Getting-started-Level1/" target="_blank">https://github.com/NIRaspberryJam/Raspberry-Jam-Resources/blob/master/Sections/Explorer-HAT-Getting-started-Level1/</a><br />
<br />
New! Scratch 2,0 offline support on Pi! This <a href="https://github.com/MrYsLab/s2-pi">example and tutorial</a> covers how to add custom blocks into Scratch to interface to JavaScript, which in turn calls Python code. This should enable support for any add-on boards to be written using their Python libraries.<br />
<br />
Following a <a href="https://www.raspberrypi.org/forums/viewtopic.php?p=1183289&sid=b18f728f41474670d906550aa72ba488#p1183289">query I posted on the Scratch Forum</a> I was pointed to <a href="http://heppg.de/ikg/wordpress/?page_id=6">http://heppg.de/ikg/wordpress/?page_id=6</a> ScratchClient, and implementation of a Scratch 1.4 and 2 interface to Python, with lots of adaptors already written for add on boards, and detailed documentation on how to extend this with your own adaptors. Lots more learning ahead!Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-74879052533759705692017-06-20T06:28:00.001-07:002017-06-20T06:28:29.237-07:00First Boot of a Raspberry Pi Zero with Raspbian Jessie LiteFor building a robot, we used a Raspberry Pi Zero with the Raspbian Jessie Lite OS. The robot does not need a graphical desktop running as it is controlled by python scripts, and this combination of low power Pi and low overhead OS should minimise the power needed to be supplied from batteries to run the computer. But it presents some challenges in getting the Pi up and running. So here is what you need to do to get the OS installed, configured and the Pi accessible over a wireless network from another computer. (See the <a href="http://adventures-with-pi.blogspot.com/2017/03/getting-started-with-raspberry-pi-zero.html">previous article</a> for how to get the Pi Zero set up with the OS installed on the SD card ready to power up for the first time).<br />
<br />
On booting up, lots of messages scroll up screen, until eventually the login prompt is displayed.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo3jpddQaT_kVeHr7FxdccvKIXY4DIT-S-9Ob-JxBVg8ll5bEJ5GjXxqJk22KbdxWga1xsR5HUf6nj9tvt2T7EG7McZuBtAfqIS9LlbPyExps7-_qrbwALWHXByprV9ZJbS7lsSVcm-0o/s1600/DSC_0516.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo3jpddQaT_kVeHr7FxdccvKIXY4DIT-S-9Ob-JxBVg8ll5bEJ5GjXxqJk22KbdxWga1xsR5HUf6nj9tvt2T7EG7McZuBtAfqIS9LlbPyExps7-_qrbwALWHXByprV9ZJbS7lsSVcm-0o/s640/DSC_0516.JPG" width="360" /></a></div>
<br />
The default user account on a new install is as follows:<br />
Username: pi<br />
Password: raspberry<br />
<br />
This gives you a command prompt, ready to type in commands. The file system had already been expanded to fill card on first boot using the latest Raspbian image, but you can check this for yourself using the 'df' command (type: df then press ENTER). With my 8GB card it displayed the following information for /dev/root<br />
<span style="font-size: xx-small;"><br /></span>
<span style="font-size: x-small;"> <span style="font-family: Courier New, Courier, monospace;">7344424 1K blocks. 861480 used. 6154748 available</span></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
These numbers are in KB, so the 6154748 available means we have around 6GB of free space. This is about right for an 8GB card, as the OS files take up some of the space, and the 8GB does not result quite that much of usable space since the formatting of the card uses some space to store the directory information and index of files. If you find you have much less space then you can use the raspi-config tool to expand the file system to fill the card. To launch this configuration tool, type:<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: Courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">sudo raspi-config</code></pre>
<br />
For full details of this configuration tool, see the <a href="https://www.raspberrypi.org/documentation/configuration/raspi-config.md" target="_blank">official documentation</a>.<br />
<br />
The first job after booting up is to get the Pi zero online by configuring the wifi network settings. We will do this using the command line text editor 'nano' to edit the network interfaces file. Open this file in the editor by typing:<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: Courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">sudo nano /etc/network/interfaces</code></pre>
<div>
<code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;"><br /></code></div>
Change the line: <b>auto lo</b>, to <b>auto wlan0</b><br />
Then change <b>manual</b> to <b>dhcp </b>inside the wlan0 block.<br />
<br />
Press Ctrl+x to exit the editor, followed by <b>Y </b>and <b>Enter</b> to save the edits into the existing file.<br />
<div>
<br /></div>
Now we have told our Pi to connect the WiFi network by default, but we also need to give it the details of which WiFi network to try and connect to. This is done in the wpa_supplicant.conf file which we can edit by typing:<br />
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
</div>
<br />
<pre style="-webkit-text-stroke-width: 0px; background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: courier, monospace; font-size: 14px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; letter-spacing: normal; line-height: 20px; margin: 0px; max-width: 100%; orphans: 2; padding: 10px; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; width: 540px; word-spacing: 0px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">sudo nano /etc/wpa_supplicant/wpa_supplicant.conf</code></pre>
(Tip: press the TAB key after typing part of the folder name or filename and it will autocomplete based on matching folders or files. This saves a lot of typing.)<br />
<br />
In the editor, add the following to the end of the file:<br />
<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">network{
ssid="MyNetworkName"
psk="wirelesspwd"
proto=RSN
key_mgmt=WPA_PSK
pairwise=CCMP
auth_alg=OPEN
}</code></pre>
<div>
<code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;"><br /></code></div>
Replace <span style="color: #222222; font-family: courier, monospace; font-size: 14px; white-space: pre-wrap;">MyNetworkName </span>with the actual name of your WiFi network, and replace <span style="color: #222222; font-family: courier, monospace; font-size: 14px; white-space: pre-wrap;">wirelesspwd</span> with the password for your WiFi network. Exit and save the file as before (<b>Ctrl+x</b>, then <b>Y</b> and <b>Enter</b>).<br />
<br />
The other settings in this network configuration are suitable for most current WiFi routers using the more secure WPA2 encryption. They have worked fine with both my BT Home Hub v5 and v6 routers. But if you have an older router or are using other network encryption settings then you may need to change these too. I found the following article useful if you are looking for further details: <a href="http://weworkweplay.com/play/automatically-connect-a-raspberry-pi-to-a-wifi-network/" target="_blank">http://weworkweplay.com/play/automatically-connect-a-raspberry-pi-to-a-wifi-network/</a><br />
<br />
Once we get our Raspberry Pi connected to our network, we want to connect to it using SSH from another computer. This is handy because unless we have a USB hub we cannot have the WiFi USB dongle plugged in at the same time as the keyboard. The newer Pi Zero W model does not have this problem as it has WiFi built in. But assuming we are using the cheaper Pi Zero here, we will need to make sure that SSH is enabled before we disconnect the keyboard. Since November 2016, the Raspbian OS distributions have SSH disabled by default. It can be enabled using the raspi-config tool, which is launched by typing:<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">sudo raspi-config</code></pre>
<div>
<br /></div>
In the config tool, select 'Advanced Options' and then 'SSH'. Choose to enable SSH, then exit the tool.<br />
<br />
If everything is ready to go, then we will need to unplug the keyboard from the USB socket in order to plug in the USB WiFi dongle. My dongle did not work when plugged into the USB hub socket on my keyboard. Possibly it would work using a powered hub? Before we unplug the keyboard we need to shut down the Pi. Do this by typing:<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">sudo shutdown now</code></pre>
<div>
<code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;"><br /></code></div>
Once the Pi is fully shut down (the green LED on the board turns off), unplug the power cord and the keyboard. Then plug the WiFi dongle directly into the Pi USB cable, and reconnect the power. When the Pi Zero boots up again if should automatically connect to the network if we got the wifi configuration right. You should see the IP address it has been assigned displayed on the screen.<br />
<span style="font-size: xx-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">e.g. 'My IP address is 192.168.1.109 ....' (followed by some alphanumeric codes)</span><br />
<br />
Sometimes two IP addresses are displayed. I am not sure why, but the first one appears to be the one which works OK.<br />
<br />
If the IP address is not displayed then the WiFi network connection likely failed. While the Pi is turned on you can unplug the WiFi dongle from the USB port and plug the keyboard back in so you can login and edit the settings files to try again.<br />
<br />
Assuming your Pi is now connected to your network, you should be able to connect to is using SSH. I used the free program WinSCP which you can download from <a href="https://winscp.net/" target="_blank">https://winscp.net/</a><br />
<br />
Install WinSCP, and use it to connect to your Pi over SSH using the IP address displayed on boot up. WinSCP is a graphical file explorer tool which enables you to copy files between a Windows computer and a Linux computer (our Pi). You can also use it to edit files stored on the Pi using Windows editors. The command terminal program Putty is included in the install, and you can directly launch this from the Login button too. Or once you are connected, you can launch a terminal session using the Putty tool from a button on the toolbar in WinSCP. Here are the options I used for my Pi (which was using the IP address 192.168.1.109 on my network).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixgPH_JBC4m2te5cM2-sQOzydg3in7STClnB1V8Rh0uDN5tN3xMUqtan1tlkLlZ535B2GWabcT7MM7ytyU-PSznFGfU7vEeEJBquVLGKbTz3rfQPQ7x52-K1rrQ6rz1AYeiLZxj_Jux0w/s1600/pi_putty_SSH_login2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="432" data-original-width="352" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixgPH_JBC4m2te5cM2-sQOzydg3in7STClnB1V8Rh0uDN5tN3xMUqtan1tlkLlZ535B2GWabcT7MM7ytyU-PSznFGfU7vEeEJBquVLGKbTz3rfQPQ7x52-K1rrQ6rz1AYeiLZxj_Jux0w/s400/pi_putty_SSH_login2.png" width="325" /></a></div>
<br />
Once you have connected using Putty, you will be prompted to enter the password for the pi user. On first login from putty, the OS warns you if you are using the default password as it is a security risk. Anyone could access your pi as root if they can make an SSH connection over your network. You should change the pi account password to something other than the default of 'raspberry' to secure your pi on the network if you are leaving SSH enabled.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUXsA43Rl39TJVs08SFAH0V-QNZjdyk58vgKXuJg-x8mGglPrPvAnz7VSGWUA0mumv2jUT6JTYZTxXjNfUUiZPiEVBsGY6sr6XtSIKskxzs2hml71_t3HIvRHawF18P9Fqlr7aVw9V1pQ/s1600/pi_putty_SSH_login.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="408" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUXsA43Rl39TJVs08SFAH0V-QNZjdyk58vgKXuJg-x8mGglPrPvAnz7VSGWUA0mumv2jUT6JTYZTxXjNfUUiZPiEVBsGY6sr6XtSIKskxzs2hml71_t3HIvRHawF18P9Fqlr7aVw9V1pQ/s640/pi_putty_SSH_login.png" width="640" /></a></div>
<br />
Now you can run commands using putty from a laptop. The screen and keyboard no longer need to be connected to the pi zero, except that without a screen connected we do not get to see what IP address the Pi was allocated on your network when it boots up. Often it will keep the IP address it had the last time, but this is not guaranteed with the DHCP configuration. There are tools you can run from a Windows computer to scan the network looking for devices, or you can change the configuration to use a static IP address so you always know what it is. But you need to make sure it does not clash with any other devices on your network. For now, keep the screen connected when you first boot up so you know which IP address to connect to over SSH.<br />
<br />
As this is our first boot up of a new Pi, we should update the packages to the latest stable versions. This is done using the command line apt-get tool. First we need to get the latest package list. Type:<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">sudo apt-get update</code></pre>
<div>
<code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;"><br /></code></div>
If you are successfully connected to the internet then this will get the latest list of packages. Otherwise it will warn you that if could not access the servers. Just because we are connected to the network does not mean that the network is connected to the internet. So check it did manage to update from the messages displayed.<br />
<br />
If you only want to update the packages already on your system to the latest versions, then type:<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">sudo apt-get upgrade</code></pre>
<br />
To upgrade the Raspbian distribution to the latest version (which will update all the packages and also remove redundant ones), you type:<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">sudo apt-get dist-upgrade</code></pre>
<br />
This distribution upgrade can take some time (over an hour), so run it when you don't want to use the pi for a while. Keep an eye on it, because you get some information on changes to read once the downloading of new packages completes (my update of a 1 month old Raspbian image after first install took around 2 minutes to download the updates and display the messages which I had to scroll through, then the installation phase of the update started and took another 38 minutes to complete).<br />
<br />
Now we have a completely updated OS, we can look at how to get additional packages. You are likely to want to run Python3 scripts, and use the Python GPIO libraries to interface to electronics you connect to your Pi. In the Raspbian Jessie Lite distribution I had, neither of these capabilities were installed already, so here is how to get them.<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">sudo apt-get -y install python3-rpi.gpio</code></pre>
<br />
The package manager will look up the dependencies for the package we are asking to be installed, and automatically install these too. So by just requesting the python3 GPIO package, we will find that Python3 is installed too. Once the install completes, you should be able to type:<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">python3</code></pre>
<br />
The Python 3 REPL environment should launch. You can run python commands directly here. Try typing to following python3 statement at the prompt:<br />
<pre style="background: rgb(242, 241, 240); border: 1px solid rgb(221, 221, 221); color: #222222; font-family: courier, monospace; font-size: 14px; line-height: 20px; max-width: 100%; padding: 10px; white-space: pre-wrap; width: 540px;"><code style="background: transparent; border: 0px; font-family: Courier, monospace; padding: 0px;">print("Hello Pi World!")</code></pre>
<br />
It should display the message in the quotes below the command. You can explore other python3 commands here. When you are done, press CTRL+z to exit REPL and return to the linux shell command prompt. Everything is now ready to start extending your Pi zero and interact with the electronics you connect using Python3 scripts.Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-53984535378451571682017-04-20T05:20:00.001-07:002017-04-20T05:20:27.532-07:00Recommended Raspberry Pi 3 Starter Set UpBased on my experience of buying a range of Raspberry Pi units and accessories, this is what I would recommend as a great set up to get started. It will give you a good prototyping rig for starting to extend the Pi with simple electronics with the minimum of trouble.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgenvRcJzT0vtXAT5h99lx2VcbrwN-qB4T1jbJDKfKW88gGRoAZSNS6cCa1PAxrGfikHETuplntFGtuty7z2EJcQVPvQyTg9Hn0PgOs3ukS2JUe5pczOOUdAdvmExbR_JvK84P7EtbhZjU/s1600/P1110312-Edit.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgenvRcJzT0vtXAT5h99lx2VcbrwN-qB4T1jbJDKfKW88gGRoAZSNS6cCa1PAxrGfikHETuplntFGtuty7z2EJcQVPvQyTg9Hn0PgOs3ukS2JUe5pczOOUdAdvmExbR_JvK84P7EtbhZjU/s640/P1110312-Edit.jpg" width="574" /></a></div>
<br />
The important items to get are as follows:<br />
<ul>
<li>Raspberry Pi 3 (the latest full size Pi at the time of writing this)</li>
<li>Official Raspberry Pi power supply</li>
<li>Micro SD Card</li>
<li>Pimoroni Pibow coupe case</li>
<li>Pibow breadboard base</li>
<li>Breadboard (5.5 cm x 8.5 cm)</li>
<li>USB Keyboard</li>
<li>USB Mouse</li>
<li>HDMI cable</li>
<li>HDMI monitor</li>
</ul>
<div>
Also pictured above (but not essential) is the Raspberry Pi camera module.<br />
<br />
The Pibow coupe case keeps all the connectors accessible, and the breadboard base add-on for this case provides a space to stick the breadboard on next to the Pi. I recommend the official Raspberry Pi power supply because it provides enough current (2.5A) to power both the Pi plus additional electronics you might add. A standard tablet charger USB power supply is typically only 2A, which is enough to power the Pi, but may cause it to misbehave if you add any additional electronics which require much power.<br />
<br />
Then to give you a great start in building some simple circuits to control, I highly recommend the Explorer HAT Pro, and the Explorer components kits.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJIGsRYvytAgjRBAzocVoe6bIDwQ4AtRxO3U0MDkLFpq1KYqxTzoe_8mQVIb83JY4TnjUXE6zFFZ4IuGwfSECVHA_xzUqAy5OdDP2-Se6Hstn1-k0q7r1BX6gfAhLQI_x1hpSGK4HrjGc/s1600/P1110315.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="494" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJIGsRYvytAgjRBAzocVoe6bIDwQ4AtRxO3U0MDkLFpq1KYqxTzoe_8mQVIb83JY4TnjUXE6zFFZ4IuGwfSECVHA_xzUqAy5OdDP2-Se6Hstn1-k0q7r1BX6gfAhLQI_x1hpSGK4HrjGc/s640/P1110315.jpg" width="640" /></a></div>
<br /></div>
<div>
You can see these in the photo above, along with the camera module (available separately). The Explorer Hat Pro provides 8 touch inputs and has 4 built in LEDs. It also provides protected inputs and outputs making it less likely you will damage the Pi when prototyping add-on circuits.<br />
<br />
The Hat includes a small breadboard for prototyping, but it quickly gets crowded. The Pibow breadboard base and case with a larger 'half size' additional breadboard attached provides a lot more room to build more complex circuits.<br />
<br />
Finally, if you have a computer monitor with built in speakers then you can use these to output sound from the Pi 3. We wrote some simple code based on the Explorer Hat Pro examples which lit up a different LED for each touch sensor, and also spoke a phrase (the kids came up with some phrases which we wrote into the code and used text to speech libraries to get the Pi to say them). The kids loved it and it caused much hilarity as the text to speech tried to pronounce what they had programmed it to say.</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
The components are all available from the usual suppliers, details of which can be found on the <a href="http://adventures-with-pi.blogspot.com/2017/03/links-scratchpad.html">links page</a> of this blog.</div>
Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0tag:blogger.com,1999:blog-3131866441334625691.post-77346523629218538342017-03-19T10:34:00.001-07:002017-06-20T06:31:31.850-07:00Getting Started with the Raspberry Pi ZeroThe Raspberry Pi zero is a great low cost bare bones board. Costing only £4 (GBP) it is incredible value. A complete computer for just £4? Well not quite, as you really do just get a bare bones board.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_qDy8HQbcvROL_9_7U4fiT9cAev42pB-sGS_2gyzgM0jXAAWtG3fYQ6j8-epY5dkwOhAKebeI5rDW10Ru5gf271OeD5vpKV5rfP1vRP1Di7QacqfU6jrbstwsMA9XLH3LqlOrlXsDhhM/s1600/P1110304.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_qDy8HQbcvROL_9_7U4fiT9cAev42pB-sGS_2gyzgM0jXAAWtG3fYQ6j8-epY5dkwOhAKebeI5rDW10Ru5gf271OeD5vpKV5rfP1vRP1Di7QacqfU6jrbstwsMA9XLH3LqlOrlXsDhhM/s400/P1110304.jpg" width="400" /></a></div>
<br />
It can be a bit of a challenge to work out just how to get started with one of these for the first time. Here we will look at what you need to actually get up and running, and the steps I took with my first Pi zero to get it booted up and connected to to internet in order to use it in our first robot. You need a few additional items to get one of these boards up and running.<br />
<br />
First, the computer needs some sort of data storage to read and write files from, and to hold the operating system (OS). These boards use a micro SD card for this purpose. You need at least 8GB of space to install the Raspbian OS. If you need more space to hold lots of files (maybe video files recorded on a Pi camera?) then you might decide to use a larger card.<br />
<br />
In order to power the computer, you need some sort of power supply. The Pi Zero will run off the USB chargers which come with most tablets (chargers which can output 2A). Smaller phone chargers may not be able to provide enough power for the board to run reliably. If you don't already have a suitable charger then you can buy a power supply specifically for the Raspberry Pi, or if you are looking to built a robot which is not connected by wires at all then a USB charger battery can be used.<br />
<br />
You will need to be able to see the computer output on a screen. To get started, this is most easily done using an HDMI cable to connect it to a TV or computer monitor which has an HDMI input. But you also need an adaptor to connect the HDMI cable to the mini HDMI port on the Pi Zero. Later this can be replaced with a remote computer connecting over a wireless network, but we need to set that up first, so a screen connected directly to the Pi using a cable is needed initially.<br />
<br />
You need a keyboard to send commands to the Pi too. This should be a USB keyboard, but you also need another adaptor to enable you to plug the USB keyboard into the micro USB port on the Pi Zero board. If you are using the graphical desktop in the full Raspbian OS then you'll also need a USB mouse. The Pi Zero only has one USB port, so you will need a USB hub of some sort to plug in both the keyboard and the mouse. In my case I had a USB keyboard which had a built-in hub, so I could plug the keyboard into the Pi (via an adaptor cable) and plug the mouse into the USB port on the keyboard.<br />
<br />
Finally, in order to connect to your Pi over a wireless network, you will need a USB WiFi dongle. You don't need to plug this in just yet though.<br />
<br />
Optional, but recommended is a case for the Pi. Otherwise you have to be careful with a powered on bare circuit board as any contact with metal objects could cause a short circuit and damage it. You can see my assembled set up below (apart from the screen which the other end of the HDMI cable would plug into).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwg-QT-syWFgWoP4xcmDy_y8A2mfoFujGRYkOmMKL1mlRDnIhoXvhx5OR5HgjA-sgZP5cdoKWA0Nnd5RBk1uA5SnrLOqENPHw-DBUJOZuf52ER0Y-UQg8a_Pohiw1yLgL90xZJFcfZT6I/s1600/P1110309.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="460" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwg-QT-syWFgWoP4xcmDy_y8A2mfoFujGRYkOmMKL1mlRDnIhoXvhx5OR5HgjA-sgZP5cdoKWA0Nnd5RBk1uA5SnrLOqENPHw-DBUJOZuf52ER0Y-UQg8a_Pohiw1yLgL90xZJFcfZT6I/s640/P1110309.jpg" width="640" /></a></div>
<br />
Before you can boot up the Pi Zero you will need to install an OS on the SD card. For our robot we used Raspbian Jessie Lite. You can buy micro SD cards with NOOBS pre-installed if you want to be guided through the OS set up. Or you can save a small amount of money by purchasing a cheap micro SD card (I would recommend getting at least a class 10 card or reading and writing from it will be a little slow). Next download a Raspbian image from the <a href="https://www.raspbian.org/">Raspbian website</a> and write the image to the SD card on a computer using an imaging program (I used <a href="https://sourceforge.net/projects/win32diskimager/">Win32 Disk Imager</a> on a Windows 10 laptop to do this). Once you have an OS image written to the SD card you can connect everything up and power on the Pi Zero for the first time.<br />
<br />
Note that the WiFi dongle is not connected yet. I tried plugging mine into the spare USB port on my keyboard, but the port did not supply enough power and the dongle was not visible to the Pi. However, once we have got the Pi zero booted up and configured to connect to our Wireless network we can shut it down, unplug the keyboard and plug in the USB dongle instead. Then when we boot it up and it has connected to the network, we can connect to it from a laptop to control it. From this point in time we no longer need a keyboard (or a screen) connected to the Pi. See the link at the end of this article for how to configure the Pi Zero to connect to your WiFi network.<br />
<br />
If you plan to connect any add-on boards or other electronics to the Pi, then you will also need to solder a 40 pin header onto the Pi Zero board. The full size Raspberry Pi boards come with these already attached.<br />
<br />
Below you can see all these essential components laid out with the bare Pi Zero board. In this case a small adaptor shim is shown instead of the micro USB to full size USB adaptor cable. It does the same job as the cable but is much smaller. Most importantly, it must be inserted into the larger USB plug the right way up or you will short circuit the power on your Pi Zero board!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2nmfvILQSoz2v2W1lFlWf6azXQyW2ifzxv8MoJN7vPxD8fn-XzeRW4xuiAxDHx531SG8xvvkVK1WowK7RjepCeSZU8O6O3capG2PxSDydMCOqADKiR2vd8WCqYYSZAKIGGAqZNXpftEM/s1600/P1110306.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="454" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2nmfvILQSoz2v2W1lFlWf6azXQyW2ifzxv8MoJN7vPxD8fn-XzeRW4xuiAxDHx531SG8xvvkVK1WowK7RjepCeSZU8O6O3capG2PxSDydMCOqADKiR2vd8WCqYYSZAKIGGAqZNXpftEM/s640/P1110306.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Most of these items can be purchased along with the Pi Zero as an 'essentials' kit from the Pi suppliers. If you are not sure where to buy all the things you might need for your Pi adventures, then take a look at the <a href="http://adventures-with-pi.blogspot.com/2017/03/links-scratchpad.html">links page</a> where I maintain links to the websites for anything I have found useful for my adventures with the Pi.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Once everything is up and running, the bare bones Pi Zero only needs the USB wireless dongle and a power supply connected. If something goes wrong with the configuration then having a screen connected is a great help though. Here is my Pi Zero with the header soldered on, the SD card inserted and the whole thing protected with a Pibow Zero case from Pimoroni. The USB WiFi dongle is connected using a shim adaptor. The HDMI adaptor is still connected in case I need to connect a screen, but once it is all working that could also be removed.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyzJoLxnn2x6II8fGtnsbFjFD5Q-VqJjrPMtm_PDVSuGdpihZ9ZzeTeSwyFllPv-kv01nw3d94GToqkSEBC3Vh0cDEXpPi-PKlew1HJNtkIst9k0zG9Dcmw11H_riutFsIuALHSQDF060/s1600/P1110307.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="574" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyzJoLxnn2x6II8fGtnsbFjFD5Q-VqJjrPMtm_PDVSuGdpihZ9ZzeTeSwyFllPv-kv01nw3d94GToqkSEBC3Vh0cDEXpPi-PKlew1HJNtkIst9k0zG9Dcmw11H_riutFsIuALHSQDF060/s640/P1110307.jpg" width="640" /></a></div>
<br />
In the <a href="http://adventures-with-pi.blogspot.co.uk/2017/06/first-boot-of-raspberry-pi-zero-with.html">next article</a> we will walk through how to configure Raspbian to get the Pi Zero connected to the internet over the wireless network, and connect to it remotely from a laptop.<br />
<br />Footleghttp://www.blogger.com/profile/05774991388160257321noreply@blogger.com0