Tuesday, 1 December 2015

Tea, Earl Grey, Hot - Replicating components

In my last blog post I listed a number of items I wanted to complete over the weekend and, well a few issues cropped up that took up a chunk of time. My Sense HAT suddenly decided it didn't like my OLED display, both worked fine when connected by themselves to the RPi, but when both were connected the I2C bus starting reporting nonsense. Luckily I have a spare which doesn't have that problem, although I've ordered another OLED just in case that suddenly needs replacing too!

Most of my attention was spent on getting the line follower sensor re-mounted on the robot, as I no longer have the plywood base to connect it to. So for this I needed to create a new mount to hold it in place. Those of you who follow my Google+ account will be aware that I purchased a second hand 3D printer and its now time to create custom parts from nothing (well some filament).

A  RepRapPro Mendel Mono

Now a 3D printer is a long way from a Star Trek Replicator, for a start its not voice controlled, designing new components is a bit more complicated than pressing a few buttons, and its far from instant to actually create your new component. They also require a bit more maintenance as well, Sunday morning the PLA decided it didn't want to stick to the base, and Monday evening the gear that feeds in the filament decided to unscrew itself. Luckily each issue only took and hour or so to get sorted (Once Pi Wars is complete I'll be spending more time getting the 3D printer setup, including printing out some spare parts for itself!).

I've been using AutoDesk Fusion 360 to design my components (Its free for hobbyists) and after a bit of practice I can put together a basic (i.e. rectangular) shape in a few minutes. Once the shape is complete I use the '3D print' option to export a .stl file, which I then import into another program to 'Slice' it into 'GCode' ready to be fed into the printer (I'm currently using the RepRapPro Slicer software). Its recommended that the resulting G-Code is copied onto the SD card built into the printer for maximum reliability, which is another step to complete. (Once I have more free time I'm sure I can streamline this a little).


To actually control the 3D printer I have a Raspberry Pi connected to it via USB which is setup running VNC. Connecting to this via WiFi I can launch the control software, select the file from the printer's SD card and set it off printing. Depending on the size and complexity of the print this can take a few minutes, or a few hours, so I mostly alternated between printing the LineFollower mount and the 'wire' mount for PiNoon, tweaking the design of one whilst the other was printing.

The 'wire' mount took about three iterations, the first being too long, the second not strong enough, with the final one needing just a little bit of tweaking to match up the screw holes (for this I used a drill to widen the holes, as that was much quicker than printing off another component).

Final design is on the right.

The PiNoon attachment mounted, I didn't have a coat hanger to test it with, so used a screw instead.
The line follower mount is a little more complicated as it needs to securely hold the sensor in place, as well as allow it to be mounted to the robot itself. To avoid trying to find a stand-off or two to hold the sensor at the correct distance above the ground I realized I could just simply 'print' out arms to hold the sensor in place. Simple right?

Well maybe not quite that simple, having items at different heights that 'float' in the air doesn't work unless its supported. Luckily the RepRapPro Slicer software will automatically insert supports to the model, but it can be a little tricky to trim it off afterwards. My first attempt has the screw mounts on the outside of the sensor, but this turned out to make the sensor a little too wide to easily connect to the robot.

Attempt one

On the second attempt I flipped them over to be above the sensor, making it much more compact, but requiring careful trimming to remove the 'support' material.

Action shot!
Attempt two

Due to some of the issues mentioned above with the 3D printer the line follower didn't finish until late last night, so I've not had a chance to connect it to the robot yet and, due to it being work's Christmas party tonight it won't get done until tomorrow. However whilst it was printing I did move the Arduino onto a Perma-Proto PCB ready to be connect up (I may just use blu-tac for this, my robot has a lot of screw holes in it already!)

So with less than four days left to do things are sorta coming together, with a bit of a question mark around the Skittles challenge!

Leo


Saturday, 28 November 2015

Its the final countdown! - One week to go

This time next week I'll be in Cambridge participating in PiWars (Assuming no more magic smoke escapes from my robot) and I have a busy weekend planned to try and pull everything together. I've been busy doing some more soldering this morning and will be doing some more this afternoon, after visiting Maplins to get supplies!

Main focus today is to get my line sensor mounted on my newer chassis, as the previous method is no longer viable. This is going to mean moving the Arduino that controls it off the bread board and onto something more permanent. I did consider moving the sensor onto the same Arduino that drives the motors, but I just don't have enough pins spare, and it would be a little fiddly connecting it up.

After that I need to work out a mechanism for holding the 'wire' for the Pi Noon challenge, which is slightly trickier now that the motors and wheels are mounted forwards of the chassis, and then tweaking the code for the autonomous challenge.

Hopefully that will then leave tomorrow for sorting out a device to help with the Skittles challenge. I have some plans but have not had time to actually build anything!  Worse case I'll just have to give the ball a good push.

There's a few other things I want to work on, but as they are extras they can wait until later.. As for other deadlines, well the 'blogging' challenge completes today (in about 30 minutes!) to ensure there's enough time for them all to be judged before Saturday. Obviously that doesn't mean I'll stop blogging, I should have at least one post before the event that (hopefully) shows OptimusPi fully functional, and I'll have a post-PiWars update as well.

So, with the clock ticking, its back to the soldering!

Leo

Thursday, 26 November 2015

Soldiering on - Soldering on

One of the issues I've had with previous robots (and other contraptions) is managing to plug cables in the wrong way round, something that's especially easy to do when using jumper leads as they are typically not joined together and can get mixed up in oh so many ways (Not to mention the fact there's 40 pins on the Raspberry Pi to actually connect them to).

To try and avoid this happening I try to add dedicated connectors for each component, preferably of the kind that can only be plugged in one way. So last night I grabbed an Adafruit Perma-Proto Pi HAT board out of the box its been living in for the past few months and began to prod it with a hot stick (well a soldering iron).


With such small components it can be difficult to rectify an error so its best to take some time to work out what you need connecting up, and where. For OptimusPi pretty much everything connects via I2C, some components using the regular I2C pins, and the rest using GPIO pins 5 and 6. However I also need to have the SenseHAT connected, and it needs to be on top so I can get at the joystick and use the LED matrix. Due to the ways that the pins connect up on the Adafruit board that just left the one side I could easily bring connections out to.

After moving things around, trying out different connections and seeing how things looked when connected to the RPi itself I decided to have the 'external' I2C connector in the bottom right corner (above the AV connector) and the OLED in the middle (covering the HDMI port, but I don't plan on using that) which leaves room in the bottom left corner for future expansion (Maybe my RTC will end up there).

Constantly checking the connections to make sure I don't wire things up backwards I added the necessary wires to connect the GPIO pins to the correct locations on the lower half of the board and, before plugging it in, uses a multi meter to double check everything was connected as expected.


As I didn't have too many right-angled connectors in my box of bits I had to modify one of the 'straight up' connectors by lowering the pins (heating them with the soldering iron and pulling them through the plastic) and bending them with a pair of pliers. So adding the I2C connector took a little longer than it needed to. However everything was finally connected, so time to apply the power.


A couple of checks using 'i2cdetect' to make sure the OLED and SenseHAT were being correctly detected and I fired up the OptimusPi binary and was happy to see the OLED working. Of course with it mounted on the side I have to go and tweak the code so the joystick works as expected. But where does that other wire go?

Well one of the other components I picked up recently was the Grove I2C hub. which I've mounted underneath the Raspberry Pi (I may move this as, whilst its nicely hidden, its a bit of a pain to reach). This replaces the I2C 'expander' I'd home-made previously, with the added benefit of ensuring you can't connect the cables backwards.


With the Raspberry Pi all connected up I turned my attention to the Arduino controlling the motors. This time it was an Adafruit ProtoShield I soldered up, and so far only the I2C connection that I've soldered in. I actually need to go and revisit this and use a proper connector (Not sure why I didn't... was getting late!) but for now this makes it a little easier to wire everything up.


I have a few other items I want to connect up to the Arduino, if I have time that is, but for now I need to make sure all the basics are working again before adding extras.

As a reminder of how little time there is left my PiWars timetable turned up today, and about the only challenge I'm ready for is the Obstacle course!

Leo

Tuesday, 24 November 2015

'Tis but a scratch! - Up and running again

Well after carefully checking all the components everything seems to be working, apart from possibly the UBEC that was powering the Raspberry Pi.  There's no sign of burnt cables, or discolourations on the Arduino or Motor driver and after re-applying power OptimusPi happily trundles around.


There's still the issue of the motors not being mounted level, and I need to swap in a replacement UBEC (currently using an Adafruit PowerBoost board to power the Raspberry Pi) but at least I don't have to order in any replacement parts!

Speaking of which, the NFC reader I ordered back in September has finally arrived... Unfortunately its probably a little to late for me to do anything useful with it.


So with this minor panic over its back to the more general case of 'running out of time' panic! I've got some soldering to do these next few evenings, sort out the motor mounts, work out how to connect the line following sensor to this new chassis, improve the code and various other things!

Leo

Puff the magic dragon - uh-oh I see smoke...

So this blog was supposed to be about how I decided I needed a bit more room inside my robot, how I switched to a large box, mounted the motors on it, added cabling so the motors can be easily swapped out, added a power switch and generally tided things up a bit.

So many wires
Unfortunately when I was setting OptimusPi up last night to take photos I suddenly noticed smoke escaping from the inside of the box... Possibly the mythical magical smoke that makes electronics work?

Quickly cutting the power (yay for the new power switch) I popped the lid off and removed the battery to check for damage. An initial glance didn't show any burnt wiring or other damage, which implies the damage was done to the Arduino which is hidden beneath the motor driver.

I've checked the Raspberry Pi and the OLED, which both seem to be working happily, but it was getting late and I didn't have time to check the state of the Arduino, so that's something I'll have to do tonight.  Hopefully its just the Arduino that got charred, and not the motor driver, as I have a spare Arduino I can replace it with (Although not a nice, shiny, black Adafruit one). But with only 11 days to go until PiWars I have a lot of work to do.

But back to the updated robot. With the motors mounted to the base I, technically, don't need the plywood base I was using previously, however it means the robot doesn't look all that pretty. I did have plans for the top, but now I'm not sure I'll have time to get anything extra done now.


One other problem I ran into is I managed to end up with motors that aren't mounted level, so it has a bit of a wobble to it. Its something that's fixable (just takes more time) but I need a working robot first, here's hoping nothing too badly damaged.

Leo

Saturday, 14 November 2015

Job's done - Code complete-ish

Today, at noon, was the deadline for the Code Quality challenge and therefore an obvious target to have my code functionally complete (The competitors are still allowed to change code up to the main PiWars event itself). So how did I do?

To keep track of the code I submitted today I created a tag in GIT called PiWars2015-CodeChallenge so I can refer back to it later (if needed) and the stats of that code snapshot are

http://cloc.sourceforge.net v 1.60  T=0.17 s (297.2 files/s, 29810.7 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C++                             20            583            594           1700
C/C++ Header                    21            258            422            564
Arduino Sketch                   6            131            221            340
Python                           2             44             55            162
CMake                            2             12              9             21
-------------------------------------------------------------------------------
SUM:                            51           1028           1301           2787
-------------------------------------------------------------------------------

So that's 51 files created and almost 2800 lines of code written... But is it complete?

In the past few weeks I've added 'ThoughtProcesses for the StraightLine and ThreePointTurn challenges. These both make use of the Sense HAT's array of sensors to determine the current heading of the robot, using it to try and maintain driving in a straight line, and for performing the turns for the three point turn. As can be seen in the following videos it doesn't always work quite right... I've tried re-calibrating the sensors a couple of times, but looks like I need to try it once more, not to mention changing the 'dead-reckoning' times to something a little more intelligent.


So, in theory, I can now enter all the autonomous challenges, although not with a huge chance of success as the code currently stands.

During testing I've been running one challenge at a time, editing the code and rebuilding it when switching between them. Obviously this is something I'd rather not have to do on the day, so I need a way of selecting between the various tasks. I had previously purchased an OLED display, but had been avoiding playing with it until I had the other functionality out of the way. Most of the example code for driving the OLED was for the Arduino so I spent some time hunting for a library that I could use from C/C++.

After wasting a bit of time searching for the wrong driver (SSD1305 instead of a SSD1306) I eventually selected the ArduiPi_OLED library to drive the display. The library does come with a few disadvantages, I now have to run my binary with 'sudo', the binary contains two library that try to access the GPIO pins and I2C bus (so far no obvious conflicts) and I can't have all my devices hanging off the same bus (which means more cables on the robot). However it has the advantage of getting things up and running now, which is useful when you have a deadline!

With the display working I added a 'Menu' class, updated the main PiWars class to create and display a menu, and to update all the ThoughtProcesses so they can be run in a background thread to not block the main thread. To navigate the menu's I'm making use of the joystick on the Sense HAT, as that will always be connected (the PS3 joystick may not be) and is simple to use. The results of all this work can be seen below


With the menu system I can select all the supported functionality, as well as shutting down the robot correctly, without yanking the power out and risking file system corruption.

So with three weeks what's left to do?  There's a couple of nice-to-have items that are just not going to make it (My RFID reader has been on back order for 2 months now, it may arrive before December but no time to add it) so I'll be spending the rest of the time tweaking my code,, practising driving and making the robot pretty, not necessarily in that order!

Leo

Thursday, 29 October 2015

I'm spinning around - Line following

The second autonomous challenge I decided to focus on was the Line Follower challenge, using the Pololu QTR-8RC reflective sensor I posted about earlier. As the sensor needs to be very close to the ground, its not something I can leave mounted all the time (The obstacle course would not be kind to it) so I needed it to be easy to add/remove.  Previously I had the QTR-8RC connected directly to the Raspberry Pi using 11 jumper leads, but that number of cables doesn't lend itself to quick attaching and/or detaching.

To try and make the sensor a little more self contained I decided to use an Arduino as a buffer device, with the sensor connected to the Arduino with the 11 jumper leads, and the Arduino connecting to the Raspberry Pi over I2C, in a similar manner to the motor driver.
The QTR-8RC sensor connected to an Arduino.
As I'm already successfully using an Adafruit Metro 328 for controlling the motors I decided to get a second one, but this time going with the 'Mini' variant to save space. Getting the  QTR-8RC sensor up and running was fairly trivial, as its just a case of grabbing the QTRSensors library written by Pololu and following the instructions. For communicating between the Arduino and the Raspberry Pi I copied the I2C code from my MotorDriver script.

For testing my Line Following capabilities I, obviously, needed to attach the sensor to the robot and, after digging around in my various boxes of supplies, discovered a couple of large bolts that would hold the sensor in the correct position. A few holes drilled later, plus a couple of blobs of blu-tac, and the sensor and Arduino was successfully mounted.


As the circuit is currently wired up on a bread board I've actually mounted everything on the rear of the chassis where there was still plenty of room. Obviously its more traditional to have line following sensors on the front of the robot, but it only takes a few tweaks in the code to make it drive backwards, and there's still plenty of time to move it before PiWars. In theory the best place for the sensor would be in the middle of the robot, as that is the point it turns around, but I don't currently have a good way of mounting it there.

With the hardware sorted it was time to turn my attention to the software. First task was to create a new 'Sensor' class for talking to the QTR-8RC sensor. As this was now controlled by the Arduino via I2C, this was a fairly trivial task (SensorQTR8RC.h) as I could just copy an already implemented I2C sensor and tweak the code.

Next was to add some actual logic to connect the sensor readings to the motor. Again this is mostly a case of copying an existing 'ThoughtProcess', tweaking it to initialize the correct sensor, sit in a loop trying to get the 'line' to stay in the centre of the sensor and we have ourselves a working ThoughtProcess_LineFollower module yes? Well turns out it wasn't quite that easy....

Other than the usual coding issues (e.g. copy and pasting a one second sleep, turning left when I should be turning right) a major problem was the Arduino resetting itself after a couple of seconds, causing the loss of calibration data and making the robot just see 'white' and drive in a straight line. My initial thoughts was that it was related to the known issue with how the I2C hardware in the Raspberry Pi deals with clock stretching (badly), so I spent a few hours switching over to the pigpio library's bit banging  I2C implementation, which correctly handles clock stretching.

I moved the QTR-8RC sensor over to the newly created 'I2CExternal' class and started running some tests. Initial results were not encouraging,  with the Arduino resetting after 20-30 requests, leaving me in the same situation I was earlier. Whilst running further tests I noticed that the Arduino was now resetting whenever I was checking if it existed, which seemed to be due to how I'd changed the 'I2C::exists()' API to work on both the 'internal' and 'external' I2C buses.

This, happily, was a 100% reproducible test case and I started to review the I2C handling code running on the Arduino. Using the time-honoured approach of  sticking an early 'return' statement in the receiveData call to determine at what point the crash was occurring. I, fairly quickly, tracked the issue to the 'for' loop that attempts to determine which command was being requested, and I spotted that I was using 'sizeof(supportedI2Ccmd)' which returns the total size of the array in bytes, instead of '(sizeof(supportedI2Ccmd) / sizeof(supportedI2Ccmd[0]))' which returns the actual number of entries in the array. Meaning I was massively reading off the end of the array and accessing memory that I didn't 'own', apparently annoying the Arduino enough to restart.

So with that change made (and ported across to the Motor Driver Arduino code) I placed my robot back onto my test track (Last years course scaled by 50%) and ended up with...



Now the robot doesn't get close to making its way around the course, but it is definitely trying to track and follow the line, which is a good starting point and something I can build and improve on over the next few weeks.

So with that in a 'working' state I'll be moving onto the next autonomous challenge, the Straight-line speed test.

Leo