Email to LCD By Way of Arduino

There are plenty of tutorials out there for this, but I’ve taken a particular tack to pull the data down on the Raspberry Pi which, because it’s fundamentally torturous, I’ve not seen anyone else take. So here goes…

The idea is that I use Tasker on my phone to set GeoFences, and then using the email plugin for it, send a message to a spare account [one that I originally set up for the motion detection]. I then haul down the email, parse out the body, and then send it down over the serial port to the LCD connected to the Arduino. All of which is so that I can “impress” my wife to [I can almost hear her eyes rolling] with a fundamentally daft piece of technology while I’m out of the house :). Let the “I’m in the pub!” messages ensue….

The easiest way to do the serial communication is using the pySerial library. Unfortunately, I don’t know Python at all, and so reverted to Perl as my scripting glue of choice. Getting this combination working was one of the trickiest steps of the whole process, as the Debian version of Perl is a little strange to navigate. I installed cpanimus, and then tried to install Inline-Python. This failed, complaining about a missing library, so I then installed python-dev via apt-get [which, in Raspberry Pi life-on-an-SD-card terms, is massive – 43mb]. I repeated the Inline-Python install which then worked fine, only to discover that there aren’t a plethora of examples explaining basics like passing in variables to inline methods.

Next step was which POP3 library to go with. I tried about 4, before settling on POP3Client [installed via sudo cpanm]. BTW, I’m not using TLS, because I’ve found it to be a little bit hit and miss with my ISP, and there are enough things that can go wrong with this project already. Needless to say you should use it wherever possible. You probably want an account dedicated for this anyway.

Before getting on to talk about the serial port comms, it’s worth taking a minute over the connecting of the LCD. I can’t solder for toffee, and managed to break the first LCD I tried [not sure how]. FWIW, this is just a random 16×2 LCD which supports HD44780, and which I ordered up from a crew called HobbyTronics [great service]. The dodgy carpentry was just a way of stabilising the display. What I ended up doing was putting a blob of solder on the end of each pin, and then pull it through from the back. There’s actually a piece of cardboard underneath to firm up the contacts – not exactly production quality, but hey, it works :).

Serial port communication is fundamentally unreliable. I experimented for quite a while with this: the termination of the data is a given, but I also tried delimiting the start of the message as well. Regardless, the repeated padding prequel data worked for me. I can imagine that this is going to be very display-dependent.

A couple more gotchas. The POP client appends what I initially thought was binary data to the string containing the body of the email message, which was appearing as a corrupt character on the LCD. It’s actually a control character, which I globally substitute out.

Having done all my sketch development and testing on the Mac, I then hit the hardy perennial of power consumption problems with the Raspberry Pi, because I have both USB ports occupied [WiFi and the Arduino]. At the standard 150 milliseconds that the scrolling method example on the Arduino website suggests, the text was borderline unreadable, so I tuned this down to 350 milliseconds. Finally, I found that the scrolling text wrapped on me, if I just offset by the length of the display string [again, as per the example]. I was running out of steam by this point, so I just subtracted the width of the display from the length of the string.

On to the code. First the POP3 to serial port client, that I run every minute as a cron job on the Raspberry Pi:

#!/usr/bin/perl
use Mail::POP3Client;
$pop = new Mail::POP3Client( USER     => "your\@email.com",
                               PASSWORD => "yourPassword",
                               HOST     => "your.email.server.com" ) || die "failed: $!\n";
$messageCount = $pop->Count();
#print "$messageCount messages\n";

# just confirming the message counter starts at 1.
# The newest message is at the bottom so we will set the body array to that value:
$textForLED = $pop->Body($messageCount);
# appended character removal:
$textForLED =~ s/(\r\n)//g;

# Only read the newest message; housekeeping is delete everything else that might be there:
for( $i = 1; $i Delete($i);
}
$pop->Close();

if ($messageCount == 0)
{
   # This is vestigial: as I run the script every minute, I don't want to display
   # any filler content if there is no email.
   #print "message count is zero\n";
   # http://numbersapi.com/number/type
   #$randNum = int(rand(5000));
   #$textForLED = `curl -s http://numbersapi.com/$randNum/trivia`;
   #print $textForLED;
}

else
{
   # this was for debug purposes:
   open (LOGFILE, ">>/home/pi/temp_sensor/logdata.txt");
   print LOGFILE "Email content: $textForLED, \n";
   close (LOGFILE);
   # Add the character to terminate:

   $textForLED = $textForLED . "^";

   for ($repeatCount = 0; $repeatCount<= 1; $repeatCount++)
   {
      serialPipe($textForLED);
   }

# This indentation can't be changed for inline code:
use Inline Python => q{

def serialPipe(textIn):
   #print 'Hi, %s.' % textIn
   import serial
   import time
   ser = serial.Serial('/dev/ttyACM0', 115200)
   for x in range(0, 5):
      ser.write('*************************************')
      time.sleep(1)
   ser.write(textIn)
   #ser.write('test message^');
};
}

and now the sketch:

#include 

// Connections:
// rs (LCD pin 4) to Arduino pin 12
// rw (LCD pin 5) to Arduino pin 11
// enable (LCD pin 6) to Arduino pin 10
// LCD pin 15 to Arduino pin 13
// LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

//int backLight = 13;    // pin 13 will control the backlight

void setup()
{
  //pinMode(backLight, OUTPUT);
  //digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
  lcd.begin(16,2);              // columns, rows.  use 16,2 for a 16x2 LCD, etc.
  lcd.clear();                  // start with a blank screen
  lcd.setCursor(0,0);           // set cursor to column 0, row 0 (the first row)
  //lcd.print("About Bleeding");    // change this text to whatever you like. keep it clean.
  lcd.setCursor(0,1);           // set cursor to column 0, row 1
  //lcd.print("time!");
  delay(3000);
  Serial.begin(115200);
  
  // if you have a 4 row LCD, uncomment these lines to write to the bottom rows
  // and change the lcd.begin() statement above.
  //lcd.setCursor(0,2);         // set cursor to column 0, row 2
  //lcd.print("Row 3");
  //lcd.setCursor(0,3);         // set cursor to column 0, row 3
  //lcd.print("Row 4");
}

void loop()
{
   lcd.clear(); 
   String ledDisplay;  
   boolean endOfText = false;
   while ((Serial.available() > 0) && (endOfText == false))
   {
      //Serial.println('looping');
      char inByte = Serial.read();
      if (inByte != '^')
      {
          ledDisplay = ledDisplay + inByte;
      }
      else
      {
         for (int repeatCount = 0; repeatCount <=3; repeatCount++)
         {
            lcd.setCursor(0,0);
            lcd.print("***INCOMING!!!!***");
            delay(2000);
            for (int positionCounter = 0; positionCounter < 18; positionCounter++)
            {
              lcd.scrollDisplayLeft();
              delay(350);
            }
            delay(1000);
            lcd.clear();
         }       
         for (int repeatCount = 0; repeatCount <=4; repeatCount++)
         {
            lcd.setCursor(0,0);
            lcd.print(ledDisplay);
            delay(1000);
            for (int positionCounter = 0; positionCounter < (ledDisplay.length() -16); positionCounter++)
            {
              lcd.scrollDisplayLeft();
              delay(350);
            }
            delay(2000);
            lcd.clear();
            delay(1000);
         }
         for (int repeatCount = 0; repeatCount <=3; repeatCount++)
         {
            lcd.setCursor(0,0);
            lcd.print("***THAT IS ALL***");
            delay(2000);
            for (int positionCounter = 0; positionCounter < 17; positionCounter++)
            {
              lcd.scrollDisplayLeft();
              delay(350);
            }
            delay(1000);
            lcd.clear();
         }  
         endOfText = true;
         ledDisplay = "";
         delay(5000);
         lcd.clear();
      }
   }
   delay(1000);
}

Moving From iOS to Android – Temporarily..?

I’ve been using an iPhone since the 3G [so about 5 years], right up to my 4S’ encounter with the washing machine. While there are many opinion pieces out there comparing the two ecosystems – just like pictures of cats – there’s always room for one more. I’m sure there are plenty of people looking at yesterday’s announcement from Apple and wondering where they are going next.

The point of no return for my moving to Android was the drop in price of the Nexus 4 to £159 a few weeks back. It is an absolute bargain for a phone that most benchmarks – I looked at GeekBench – put on a par with the iPhone 5. The additional real estate on the screen is a joy, and one which I think would be the single toughest aspect of a move back to the iPhone. The battery life is hard to compare with a handset that was nearly two years old and because of adapting usage patterns [more on this later], but it’s certainly very good. It’s only paranoia that has stopped me from charging more than once a day – and even then only on a couple of occasions.

The actual mechanics of my move were simple: for instance, I’ve used Google Contacts and Calendar for years. The first app that I bought was Tasker, which epitomises the flexibility of the platform. It can be a little bit tricky to navigate, especially as the majority of the documentation predates the current UI, but I’m getting there, with various functions set for when I hit / leave my home wifi, when I plug in headphones, and so on.

So on to some of the stuff that’s not so hot. I have a side-by-side comparison with one very specific iPhone app which I used every day for years on my early morning walk to the station: TuneIn Radio. It is now completely unusable: I get about 10 seconds of radio followed by 40 seconds of buffering. This could be specific to the carrier [I haven’t changed, it’s just what the handset offers], but on paper HSPDA should be faster than the 3g service I was using. Stuck in the back corner of our house – again a side by side comparison – the wifi reception is also not as good as on my 4S.

The various views that the Nexus desktop provides: the home screens versus the All Apps view that runs flows into the unkempt wilderness that is pages and pages of widgets – I mean who thought that was a good idea? I know why it’s there, it’s just messy.

A few more mini-gripes. I’m not that keen on the music app, and haven’t really found a podcast app that I’m sure is a keeper [BeyondPod seems to be popular but the full version for £4.49 strikes me as pretty expensive]. In the interest of balance, it has to be said that the podcast app on the iPhone had morphed into a real frustration. It was a dark day when it was carved out of warm embrace of the iPod app: the cost of not synching podcasts by wire was something that was borderline unusable. Maybe iOS 7 will bless us [and I still cradle my iPad every day] with something that actually works.

One of my biggest gripes is with the permissions list that apps are looking for – the double edged sword of flexibility seems to be that developers throw everything at the wall on the off chance that something will stick. I am absolutely prepared to embrace this for Tasker – it needs permissions to do what it says on the tin – and the liberty of life outside Apple’s walled garden is, if you’ll pardon the mixed metaphor, a breath of fresh air. However, the list of perms that that the LinkedIn app [an example of one of many that I’ve passed on] is faintly terrifying. The ability to go in with a pair of tweezers, and toggle perms on a per app basis, is something that iOS does very well. It is coming apparently in 4.3, as a quick google of ‘app ops android’ will show.

The opinion I’ve been fomenting over the last couple of weeks extends what I already knew about the flexibility of the platform, pre-adoption. Fair enough, it is it there for you in Android, but I think that what’s left behind for the average person who couldn’t be bothered is not as polished or well considered. I think the ‘average person’ in this instance subdivides into two: people who either skim across the surface, or just install software with impunity.

Apple has a very accessible platform, and one that protects you from potentially poor decision making. I’m sure there are plenty of people out there wondering why their phone is glowing at night, when it’s churning through a dozen fat processes in parallel in the background. [Apple have been particularly conservative here, and the whole background process functionality was something of a hobby for me – right up until Washing Machine Day :(. It will be interesting to see how the new background functionality continues to develop from iOS 7 onwards.]

I’m only a few weeks into Android so I’m sure my opinion will refine, if not change. Was the move off the iPhone one-way? I’m not sure. Would I ever consider buying a ‘premium’ Android phone? No, I really can’t see it. That takes you into OS fragmentation territory, and an experience that is still predicated on good old Android.

One other thing I’m pretty sure about: I’m not going to develop for it. I have spent the last couple of years teaching myself Objective C and I can’t face Java!

iPhones and Washing Machines: Limping to the Finish Line

My iPhone 4S had an unfortunate encounter with the washing machine at the weekend, which amounted to about 20 minutes of water exposure – not to mention detergent, and whatever goodies conditioner contains [for that softer, fresher smelling iPhone!]. We tried the recommended bag of rice trick for 24 hours, which didn’t work. When I opened it afterwards it was still soaking wet, and the battery was leaking. I took out the motherboard and dried it off, and spotted some corrosion on the camera connector. Clearly, any recovery from the condition it was in was going to be a borderline miracle, but I thought ordering up a new battery was worth a shot.

I duly replaced the battery tonight [all told about 2 1/2 hours worth of fun – it’s late!] and, rather surprisingly, it booted up with iTunes presenting me with a request to unlock the device. Rather less surprisingly, the screen doesn’t work. I did a bit of searching to find out which connector was for the screen data [I can find no others that drive the screen in any separate way], and spotted a serious amount of corrosion which I either missed at the weekend, or which has subsequently appeared. Here’s a macro shot before I cleaned it with a toothbrush:

Corrosion

…and after. Magnification is slightly better with this shot because I used a cheap and nasty extension tube:

Culprit

In the top right, the third contact from the end appears to have completely corroded. While it may not be the only damage stopping the screen from working, it’s got to be part of the problem.

I was planning on upgrading to whatever Apple releases in the next couple of months anyway. In the meantime, I have the dubious pleasure of a Nokia clamshell from the previous decade. I’d forgotten what a joy predictive text was :).