© James R. Strickland 2016

James R. Strickland, Junk Box Arduino, 10.1007/978-1-4842-1425-1_3

3. Kick the Tires, Light the Fire

James R. Strickland

(1)Highlands Ranch, Colorado, USA

When we’re done with this chapter, you’ll have either a working Cestino or a pile of malfunctioning ICs and a bone to pick with me. We’ll run a couple sketches on it for fun, to make sure it’s working, and that we can program it, and to demonstrate that yes, it does function in a mostly Arduino fashion before we go our own direction. My hero Cestino, the one in the photos, is in exactly the same state, so I’m with you. Let’s get started.

The Stuff You Need

New Parts

  • Your Assembled Cestino

  • A 120Ω resistor as a dropping resistor for the speaker. If your speaker is much higher or lower impedance than 8Ω, you’ll need to calculate this value yourself.

New or Used Parts

  • The speaker

  • Your existing Arduino, for use as an ISP (In-System Programmer) to install the bootloader onto the Cestino.

Software

  • If you haven’t already downloaded the Cestino package, now’s the time. Make sure to get the latest version, if there’s more than one by now.

  • Ditto the Arduino software itself. You will need Arduino 1.6.5 or later. Earlier versions will not work with the various add-ons in the Cestino package. Get it from https://www.arduino.cc/en/Main/Software directly. If you’re feeling brave, you could even get the nightly build version on that page, but I haven’t had good luck with it.

  • You’ll need Mark Fickett’s arduinomorse library. Get the most current version from github here: https://github.com/markfickett/arduinomorse . If you’re already a subversion user, you can get it with that, obviously, or you can click on the download zip link on the same page.

Bootloader and Core

By now, I’ve used the words bootloader and core a lot. I’m going to use them a lot more, so we should probably be clear on what they are.

Bootloader

When you buy an Arduino, the microcontroller on it (usually an ATmega) comes preprogrammed with a bootloader. The bootloader is a small program that stays in program memory and lets you load sketches. The bootloader runs when the microcontroller is reset, and listens for a second (at least with the Optiboot bootloader we’re using) for commands from AVRDUDE, which is inside the Arduino application. If it doesn’t get anything from AVRDUDE, it transfers control to whatever sketch is loaded.

When you upload a sketch, the Arduino application calls AVRDUDE to do the work. AVRDUDE resets the Arduino using the RTS-Reset line (remember that from the last chapter?) and, within that second, establishes communications with the Arduino. Once communications are established, it uploads the sketch, and resets the Arduino again.

When the Arduino resets this second time, AVRDUDE doesn’t have anything to say, so after one second elapses, it starts the sketch .

Core

The core software is a library of objects (in the Object Oriented Program sense) that sketches can call to talk to specific hardware on the microcontroller. When your sketch says digitalWrite (pin number), it’s calling a method in one of these objects, rather than talking to the microcontroller itself.

This is called abstraction . Abstraction might seem like it reduces efficiency, and frankly, it does. In exchange, however, it lets the same sketch run on multiple models of Arduino, including the Due, which runs on a completely different microcontroller than the ATmega series. The abstraction of the core provides a standard interface between the sketch and the hardware.

A Little History of Software Abstraction

In the days of the 8 bit desktop computer, we used operating systems like DOS and CP/M. Both of these relied on a BIOS that was little different from the Arduino core, and both contained ways of loading user programs that are, if you squint enough, very similar to the bootloader. There were many programs where you put the floppy in the drive, hit the reset button or turned the computer on, and they booted themselves into the computer and ran.

Those old computers were slow. Every instruction mattered, so programmers were often tempted to bypass those interfaces and talk directly to hardware. This worked. They extracted far more performance from those old machines than anyone thought possible, but there was a cost.

If there were no interfaces defined in the BIOS or the operating system, or if you had software that was talking directly to hardware, you had to make sure those programs knew how to talk to your new hardware. Word processors, for example, had to know about your specific printer. On my CP/M machine today, it still makes me chuckle that Wordstar had to know how to print to various printers itself. Most of those printers are long extinct, but one of them, the Epson MX-80, introduced in 1980, spoke a proprietary printing language called ESC/P. Today, in 2015, 35 years later, Epson still lists impact printers on its website that speak ESC/P, and in theory, Wordstar for CP/M could print to them. Abstraction is a powerful thing .

Set Up the Arduino Application

Once you have the Arduino application version 1.6.5 or later running on your host system, go ahead and start it. Open the Preferences window.

Mac users, go to the menu bar at the top of your screen, and select Arduino ➤ Preferences.

Windows and Linux users, at the top of the Arduino window, click on File ➤ Preferences.

What we’re looking for is the exact location of your sketchbook. There are default locations, but you can put it anywhere you like, and different platforms call it different things, so just look in the Sketchbook location: field of your Preferences window, open Finder or Explorer or Nautilus and navigate there. Linux and Mac users, you can cd there in a shell window if you prefer. (For all intents and purposes, a folder in the various GUIs and a Directory in a shell window are the same thing).

While you have the Preferences window open, I strongly recommend setting the Display line numbers option, as well as Show verbose output on both compilation and upload. This means there will be a lot more stuff going by in the lines at the bottom of the Arduino application window when you compile and upload a sketch, but it’s information we may need for debugging.

Tip

You really can put your sketchbook anywhere on your system. I actually have mine in my Dropbox folder so I can get at it from my Linux machine, my Mac, my Windows virtual machine ... you get the idea.

Once you’re in the right place, you should be able to see all your existing sketches. If so, go ahead and shut Arduino down. It won’t pick up the changes we’re going to make while it’s running.

The Arduino application is an extendable IDE (Integrated Development Environment), so we can add boards and utilities to it fairly easily if we put them where the application looks for them. We could edit the Arduino application’s internal folders, but we don’t have to. It scans the hardware and tools directories in your sketchbook, too, if they exist .

In the Cestino package you downloaded, there are three folders: cestino, Burn_Preflight, and Cestino_Sketches. Drop Cestino in the hardware folder, and drop Burn_Preflight in the tools folder. If either of these folders don’t exist inside your sketchbook folder, go ahead and create them. Drop the Cestino_Sketches folder into your sketchbook folder itself.

Now when you start up the Arduino application, you should see a new line in the Tools menu item called Tools ➤ Bootloader Burn Preflight Check. When you select Tools ➤ Board, you should have a new option: Tools ➤ Board ➤ Cestino 1284p 20MHz using Optiboot.

ISP: In Circuit Programmer

Arduino application still running? Good. It’s time to set your existing Arduino up as an In-System Programmer (ISP) so we can use it to burn the bootloader onto the ATmega1284P.

Wait, what?

Some ICs are programmable. The ATmega1284P certainly is, but other types such as EEPROMs (Electronically Erasable Read Only Memory), and flash ICs are, too. In the bad old days, as we’ll see when we get into EPROMS in Chapter 8, you had to socket these ICs so you could take them out any time they needed programming, erase them, and burn a new program into them. An In-System Programmer, combined with either a proprietary system connector or a standard JTAG (Joint Test Action Group) port lets you program the IC without taking it out. Normally, ISPs are rather expensive, proprietary equipment. Atmel’s programmers are reasonably affordable at about U.S. $60 each, and if you have one, you can skip this step and use it. Likewise, if you have the optional universal programmer, you can use that as well, but you’ll have to extract the ATmega1284P from the breadboard to program it. Make sure you get pin 1 back where it belongs when you put it back.

Note

If you have a proper ISP or a universal programmer that can program ATmega1284Ps, things are different for you. ISPs can usually be selected with the Tools ➤ Programmer menu item, and a great many are in there. Universal programmers will want a .hex file to upload, and the modern Arduino application can export these with the Sketch ➤ Export Binary menu item. With the verbose output options set in the Arduino application, it will even tell you where it put them.

Arduino as ISP

For those without a dedicated ISP, don’t worry. There’s an example sketch that comes with the Arduino application that lets most any old Arduino do the job of an ISP. I’m using an Adafruit DC Boarduino, but nearly any 5 volt Arduino with a separate USB chip should work. (At this time, ATmega32Ux boards like the Leonardo don’t work with ArduinoISP). Your Cestino, once it’s built, will also work.

How ArduinoISP Works

Your existing Arduino does three jobs during this process:

  • Provide power to the Cestino

  • Communicate with the ATmega1284P with the SPI protocol

  • Receive the Bootloader and Core software from the host system and forward it to the Cestino

The Arduino application will call a separate program built into it called AVRDUDE (AVR Downloader/UploaDEr). AVRDUDE handles all communications between the host computer and the AVR/ATmega, and generates most of the text that shows up in the debug window of the Arduino application. AVRDUDE will signal your Existing Arduino over the usual USB connection and ask it to open communications with the ATmega1284P. The ArduinoISP sketch lets your existing Arduino do exactly that.

AVRDUDE tells ArduinoISP to program the “fuses” of the ATMega1284P. These software-configurable switches, among other things, tell the ATmega1284P where to get its clock signal, what kind of signal to expect, and how to calibrate its internal delays so it can communicate properly with whatever clock it’s been configured for. It’s an absolutely critical step.

AVRDUDE then sends the bootloader and core, byte by byte from the files you installed in the hardware folder of your sketchbook folder .

If all goes well, the last thing that happens is that AVRDUDE resets the ATmega1284P, and when the ATmega finishes resetting, it will be a functioning Cestino.

Set Up the ArduinoISP Sketch

Connect your existing Arduino to your host computer with the usual USB connection. Is your Arduino so old it’s using 9 pin RS-232 and has an external power supply? Awesome. That will work fine, too. Check the Board and Port settings and make sure both are correct for your existing Arduino. You’ve probably loaded hundreds of sketches on your Arduino already. That’s all we’re doing at this point.

In the Arduino application, select File ➤ Examples ➤ ArduinoISP, and upload that to your Arduino.

Set the Programmer and Board in the Arduino Application

Once you have successfully loaded your existing Arduino with the ArduinoISP sketch, it’s time to configure the Arduino application so that it sends the right data to the right place. Things can get a little confusing doing this.

Remember, we’re not uploading a sketch to your existing Arduino. We did that. The ArduinoISP sketch is running on your existing Arduino, waiting for you to send data to it over the usual serial port, so it can send that data to the Cestino’s ATmega1284P. We need to tell the Arduino application what data to send that will ultimately wind up on the Cestino.

So hit the Tools ➤ Board menu item and go all the way down to the bottom and select Tools ➤ Board ➤ Cestino 1284P 20Mhz Using Optiboot item. This tells AVRDUDE what bootloader to send. Then select Tools ➤ Programmer ➤ Arduino as ISP.

Make sure you select Arduino as ISP and not ArduinoISP, despite the sketch being called that. The ArduinoISP programmer is a dedicated ISP with an unfortunate and confusing name, and it communicates differently. We want Arduino as ISP. If it sounds like I spent hours chasing nonexistent bugs from getting this wrong, you’ve got a good ear.

Leave the port setting the same .

Wire your ArduinoISP into the Breadboard

Now that we have the software all set up, it’s time to wire your existing Arduino into the Cestino breadboard , as shown in Figure 3-1.

A340964_1_En_3_Fig1_HTML.jpg
Figure 3-1. ArduinoISP wired to Cestino
Note

SPI stands for Serial Peripheral Interface. It is a synchronous serial protocol, which means it transfers one bit at a time in each direction, synchronized to a clock signal. There are at least two devices on a given SPI bus, the master and at least one slave. The master device sends the clock via the SCLK (sometimes called SCK) line and signals which slave may communicate with it via the Slave Select, or SS line. The MOSI (Master Output Slave Input) line sends data from the master to whichever slave is selected, and MISO (Master Input Slave Output) line sends data from the slave that is selected to the master.

In order for SPI to work, obviously, there must be four connections between the devices: SCLK, MOSI, MISO, SS, as well as a ground connection. In order for your Arduino to burn the bootloader onto the Cestino, we’re going to ask your Arduino to provide 5 volt power as well.

Table 3-1 shows what SPI signals are on which pins for several of the most common Arduino types, as well as on the Cestino. Notice that these signals are also found on the ICSP port on most Arduinos and Arduino compatibles, so in many cases you can use the ICSP port instead. You’ll need female-to-male jumpers to access those pins, however.

Table 3-1. SPI Pin Diagram

Board

MOSI

MISO

SCK

SS

Reset

Uno, Duemilanove, and most ATmega328P based clones

pin 11

ICSP 4

pin 12

ICSP 1

pin 13

ICSP 3

10

Reset

ICSP 5

Mega 1280/2560

pin 51

ICSP 4

pin 50

ICSP 1

pin 52

ICSP 3

53

Reset

ICSP 5

Cestino

pin 6

pin 7

pin 8

pin 5

pin 9

On the Cestino, the SPI port begins at pin 5, with the SS pin. MOSI is on pin 6, MISO is on pin 7, and SCK is on pin 8. Since the ATmega1284P is the slave in this arrangement, the SS line from your existing Arduino is wired to the Cestino’s reset pin. (The Cestino’s own SS line is only active when it is the master.) Make sure to connect it directly to the Cestino’s reset line, and not on the ground side of the reset button or the RS232 side of the coupling capacitor.

Wire the Arduino’s MOSI line to pin 6, the Cestino’s MOSI line. Wire the Arduino’s MISO line to the Cestino’s MISO line on pin 7, and wire the Arduino’s SCK to pin 8 on the Cestino, the SCK pin.

But wait. There’s more.

Remember that any voltage is relative. Without a ground, SPI’s voltages have no common reference between the Arduino and the Cestino. So wire a ground from one of the many GND pins on your Arduino to the - bus on the Cestino board, preferably close to the ATmega1284P. Because we’re asking your Arduino to power the Cestino as well, wire one of the +5v lines on your Arduino to the + bus on the Cestino.

Now, hopefully, we’re ready.

Preflight Check

I know it’s tempting. I’ve done this hundreds of times now, and I’m still tempted to assume everything is right and hit the burn bootloader button. Don’t do it. Not yet. There are a lot of things that can go wrong. If they do go wrong, as I discovered the hard way, you can make the ATmega1284P unable to communicate at all. You can brick the chip. The problem is the fuses.

Fuses, in ATmega parlance, are programmable switches used to configure the ATmega. Once upon a time, these would be actual fuses, which could be blown (once) to set configuration. They set critical parameters like, among other things, whether the ATmega can be programmed over its SPI port, what kind of clock it’s using, and what speed the clock is running at. If these parameters are set wrong, your ATmega may not be able to boot at all, or if it can, it may not be able to communicate, even over SPI. If SPI doesn’t work, for whatever reason, your existing Arduino running ArduinoISP will not be able to program the ATmega. If the wiring between your existing Arduino and the ATmega1284P on the Cestino isn’t right, or is noisy, AVRDUDE will try to set the fuses anyway. The results are usually wrong.

It’s not all bad. If you have a universal programmer, it’s fairly straightforward to load the ATmega into it and manually set the fuses back to their default values. I’ve done that a lot, but I had to assume that you, the reader, might not have a universal programmer, and that leaving you with a bricked ATmega1284P in the third chapter of this book wasn’t going to go over well, so it would be better to avoid messing up the fuses in the first place.

Remember Burn_Preflight that you dropped into the tools folder of your sketchbook? That’s what it’s for. Got a power light on your existing Arduino? Everything hooked up? Good. Let’s see if it works.

Go to Tools ➤ Bootloader Burn Preflight Check and select it. With the verbose output turned on for compile and upload as I suggested, you should see some output. Lots of output. It should look something like Listing 3-1.

Listing 3-1. Successful Burn Bootloader Preflight Check
Hello from Burn_Preflight
/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/avrdude -C/Applications/Arduino.app/Contents/Java/hardware/tools/avr/etc/avrdude.conf -v -patmega1284p -cstk500v1 -P/dev/cu.usbserial-AH02F147 -b19200


avrdude: Version 6.0.1, compiled on Apr 14 2015 at 16:30:25
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch


         System wide configuration file is "/Applications/Arduino.app/Contents/Java/hardware/tools/avr/etc/avrdude.conf"
         User configuration file is "/Users/jim/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping


         Using Port                    : /dev/cu.usbserial-AH02F147

[Lots of stuff snipped for brevity]

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.05s

avrdude: Device signature = 0x1e9705

avrdude done.  Thank you .

Got something like that? Is the device signature 0x1e9705? Good. That’s a successful preflight check. You might want to read the error messages for future reference, but you don’t have to. Got something else? Read on.

Programmer Not Responding

If your output looks more like this:

Hello from Burn_Preflight
[Lots of stuff snipped out here]
         Using Port                    : /dev/cu.usbserial-AH02F147
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
[Lots more retries]
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00
avrdude done.  Thank you.

you need to check that the ArduinoISP sketch is running on your Arduino, and that the 5v and GND lines are connected to the + bus and the - bus of the Cestino correctly.

If your output says that the programmer is not responding but you’re not getting multiple attempts, like this:

Hello from Burn_Preflight
[lots of stuff cut out]
         Programmer Type : STK500
         Description     : Atmel STK500 Version 1.x firmware
         Hardware Version: 2
         Firmware Version: 1.18
         Topcard         : Unknown
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us


avrdude: stk500_recv(): programmer is not responding

check the SS/Reset circuit and make sure it’s properly connected. If you’re sure it is, try pressing the reset button on both the Cestino and your Arduino.

Programmer not responding errors can also come from USB getting into the wrong state. If you’re getting them, and you’ve tried everything else, try powering the host computer all the way down and turning off any USB hubs between it and your existing Arduino. Particularly with Linux hosts, there seem to be some issues in the Arduino Application’s USB handling that leave the usb port in an unusable state.

Device Signature Error

Sometimes the preflight check will appear to run, but the results aren’t right. You might get output like this:

Hello from Burn_Preflight
[Lots of other stuff cut]
avrdude: AVR device initialized and ready to accept instructions


Reading | ################################################## | 100% 0.07s

avrdude: Device signature = 0x1e9705
avrdude: Expected signature for ATmega328P is 1E 95 0F
         Double check chip, or use -F to override this check.


avrdude done.  Thank you.

It looks like a successful read, but AVRDUDE is complaining. Notice where it says Expected signature for ATmega328P is 1E950F. We’re not trying to program an ATmega328P. We’re trying to program an ATmega1284P. Go back to Tools ➤ Board and select Tools ➤ Boards ➤ Cestino 1284p using Optiboot, all the way at the bottom of the menu.

If the expected signature is 0x1E9705, but the device signature you got is 0x1E9706, then despite my warnings you got the ATmega1284 instead of the ATmega1284P. You’ll have to stop and order an ATmega1284P.

Device Signature Yikes Error

If your output looks like this:

Hello from Burn_Preflight
[Lots of stuff snipped out]


Reading | ################################################## | 100% 0.07s

avrdude: Device signature = 0x000000 (retrying)

Reading | ################################################## | 100% 0.06s

avrdude: Device signature = 0x000000
avrdude: Yikes!  Invalid device signature.
         Double check connections and try again, or use -F to override
         this check.
avrdude done.  Thank you.

Check your SCK, MISO, and MOSI lines. Remember that SPI, unlike RS232, expects the same line on both devices to be connected together, so MOSI goes to MOSI, MISO goes to MISO, and SCK goes to SCK.

Could Not Find USBtiny Device Error

This error is my favorite. This is what it looks like if, despite my warning, you selected ArduinoISP as the programmer instead of Arduino as ISP.

Hello from Burn_Preflight
[Lots of stuff snipped out]
         Using Port                    : usb
         Using Programmer              : arduinoisp
avrdude: Error: Could not find USBtiny device (0x2341/0x49)


avrdude done.  Thank you.

If you see this, click on the menu in Tools ➤ Programmer and scroll down to Tools ➤ Programmer ➤ Arduino as ISP and select that .

Burn the Bootloader

Everything ready? Good. Getting clean preflight checks? Good. Let’s hook our little monster up to the lightning. Click on Tools ➤ Burn Bootloader.

Wait for it ...

Is the LED flashing, as in Figure 3-2? In groups of three flashes? That means the bootloader is restarting continuously. That’s a good thing. It’s a heartbeat.

A340964_1_En_3_Fig2_HTML.jpg
Figure 3-2. Cestino Powered with LED Flashing

Congratulations. Your Cestino is alive. It’s on life support from your existing Arduino, but it’s alive. Let’s see if it can stand on its own. Disconnect your Arduino from the Cestino and plug the USB to TTL cable into the 6 pin header on the Cestino, making sure that the ground wire on the cable is on the pin connected to the – bus (black toward the ATmega1284P, green away from it, assuming your breadboard looks like mine).

Blink Pin 1: It’s Alive!

The usual sketch for this moment is the Blink sketch from the Examples dropdown of the Arduino application. Unfortunately, it won’t work for us. The standard Arduino has its LED on pin 13. Because we’re using the ATmega1284P’s natural pin layout, our pin 13 is where the clock signal goes in, so a sketch can’t access it. Our LED is on pin 1. This is something we’re going to have to get used to any time we use a traditional Arduino tool, so we might as well start now. Go to File ➤ Examples ➤ Basics ➤ Blink and open it.

Some versions of the Arduino app aren’t as careful as they should be about not letting you write to the examples, so we’ll just make a copy and work on the copy. Go to File ➤ Save As... and save it as blink1.

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.


  Most Arduinos have an on-board LED you can control. On the Uno and
  Leonardo, it is attached to digital pin 13. If you’re unsure what
  pin the on-board LED is connected to on your Arduino model, check
  the documentation at http://www.arduino.cc


  This example code is in the public domain.

  modified 8 May 2014
  by Scott Fitzgerald
 */


// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);
}


// the loop function runs over and over again forever
void loop() {
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

Notice how everything refers to pin 13? Change all those references to pin 1, so it looks like this:

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.


[Comments snipped for brevity]

  This example code is in the public domain.

  modified 8 May 2014
  by Scott Fitzgerald
 */


// Modified 20-June-2015 to use pin 1 (portb pin 0) of the Cestino board
//by Your Name Here.


// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 13 as an output.
  pinMode(1, OUTPUT);
}


// the loop function runs over and over again forever
void loop() {
  digitalWrite(1, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);             // wait for a second
  digitalWrite(1, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);             // wait for a second
}

Please, please, please make sure you annotate this version of Blink to tell the world what you did with it, and what those changes are for. In a year, when you accidentally grab Blink1 instead of Blink for a regular Arduino, you’ll thank yourself when that comment pops up to tell you why it won’t work.

You can also use my version of blink1 in the Cestino_Sketches folder.

Or Not So Much: Troubleshooting

If your Cestino passed the Bootloader Burn Preflight Check, and you get the continuous sequence of three flashes, a pause, then three more flashes after you bootload it, the Cestino is correctly programmed. The error messages you get should be largely the same as the ones from the preflight check, but recovering from some errors may be a lot harder.

Programmer Not Responding

If the Programmer Not Responding error rears its ugly head again during bootloader burning, you have a couple options. Re-run the preflight check and see if it shows up there too. If it does, it’s possible your USB port has gotten into an unusable state. Current versions (1.6.5) of the Arduino application seem to have some intermittent USB problems, particularly on the Mac, so try shutting everything down. Make sure the pin 1 LED on the Cestino goes out and stays out, and then start the system up again (cold start it) and see if the preflight check works now. If it does, go ahead and try the bootloader burn.

Wrong Sketch?

If loading the bootloader seemed to go smoothly, you’re getting the three flashes, pause, three flashes output, and the sketch uploaded, but nothing’s happening, press the reset button on the Cestino. If you get the three flashes, that means the bootloader is starting, but for whatever reason, the sketch isn’t lighting the LED.

Double check that your sketch is trying to light pin 1 and not pin 13, or that you didn’t accidentally upload the empty demo sketch. Weird things happen late at night.

Power or Clock Problems, Perhaps?

Is your Cestino getting any power? Set your multimeter to DC volts (Direct current: current which does not oscillate. Like the current from a battery) and to a scale where 5 volts will show up well (on my cheap meter this is the 0-20VDC scale) and go over the pins on the ATmega1284P itself and make sure you get 5 volts between pins 10 and 11, (pin 10 is Vcc, 11 is Ground) and the same five volts between pin 30 (Ground) and 31 (AVcc) Then check the oscillator. Pin 7 is ground, pin 14 is Vcc.

Is your Cestino getting a clock signal? Disconnect power from the Cestino (pull the USB plug out of the host computer) and set your meter for Ohms (Ω) on whatever the lowest scale is. Check to make sure pin 8 of the Oscillator and pin 13 of the ATmega1284P are connected. Also make sure nothing is plugged into pin 12. if something is plugged in there, it can jam up the signal from the oscillator, and that will keep your Cestino from running.

Also, check to make sure the oscillator is a 20Mhz oscillator. 16Mhz may work for uploading the bootloader (SPI’s timing is handled by its external SCK line) but it won’t work for RS232, which is what we’re sending the Cestino directly. If the delay between the three-flash sets seems much longer than a second, be suspicious. It’s noticeably slower even with a 16Mhz oscillator.

You might wonder how the Cestino could pass the preflight check without having a proper clock signal. As they come from the factory, ATmega1284Ps use an internal 8Mhz clock. As long as the IC has power and ground, it will work. Once we set the fuses, however, the ATmega is looking for a 20Mhz external oscillator on pin 13, and nothing else will do. If you have an oscilloscope or a counter or a logic analyzer capable of reading 20Mhz signals (wish I had one of those) you can check to see if the clock signal looks good. If it doesn’t, or you’re suspicious of the oscillator in any way, replace it. They’re cheap. You might consider getting a second ATmega1284P in the same order, as long as you’re paying postage.

ATmega1284P Is Bad?

Sometimes you get a bad IC. Whether they were bad from the start, or something happened to them in storage, or shipping, or your parts bin, some days things just don’t work. If your ATmega is still dead cold after a couple hours of being connected to power, or if for any other reason you think your ATmega is dead (or bricked), pull the USB cable from the host computer to disconnect power, and gently slip your screwdriver under the ATmega and lift it from the breadboard a bit. Then slip the screwdriver further under it, lift some more, and so on until the whole IC is free.

Before you toss the ATmega, take a quick look at its pins. Obviously, they should all stick down, and they should all be in two neat lines, one on each side of the package. Sometimes, when you push an IC into your breadboard (or a socket), a pin or two won’t be aligned right and they’ll get mashed into the bottom of the package instead of connected. Diabolically, from the top, you usually can’t tell. With the IC in your hand, you can. If one of the bent pins is a power pin, the clock pin, one of the RS232 or SPI pins, that could very well be the problem. Gently bend the pin back to position. You can bend the pins on an IC once, sometimes twice and get away with it. Further bends will snap them off, and if one snaps off, it’s time to replace the ATmega. If you have part of the pin left, and you want to try soldering a piece of wire to it, be my guest, but ATmegas aren’t that expensive .

The Morse Code Practice Translator

Hopefully by the time you get here, your Cestino is sitting, merrily flashing its LED at you. We could do a lot of tests to verify its performance (I did) but frankly, that’s dull. Let’s have some fun with it instead. We’ll do it the traditional Arduino way, before we head off into the woods. We’re going to build the Morse Code Translator, shown in Figure 3-3.

A340964_1_En_3_Fig3_HTML.jpg
Figure 3-3. Morse Code Practice Translator

What the Morse Code Translator will do is take messages from the host computer and translate them into tones over a speaker. I only know a little Morse, but if you’re learning, a computer can give you the kind of endless repetition it takes to commit this ancient code system to memory.

Download the Arduinomorse Library and Install It

We could write our own Morse code library, but this is a mini-project, and it’s been done, so let’s just download a library instead. It’s the Arduino way. If you haven’t already done so, go to https://github.com/markfickett/arduinomorse and either download the library with subversion or click on the download zip link, and uncompress the archive. Either one will work. Drag the arduinomorse-master folder into your sketchbook folder and drop it in the libraries folder. If the libraries folder doesn’t exist, go ahead and create it. Terminal users in Linux or Mac, cd, cp, and mkdir work, as always.

The arduinomorse-master library contains several objects that we need to write the Morse Code Practice Translator.

A Quick Introduction to Object Oriented Programming

Nearly all Arduino sketches are written in a mishmash of C and C++. Mostly they’re C, an old school functional language, except where they need to call parts of a library, or some parts of the Arduino core. The arduinomorse library is written in C++, and it’s very object oriented, so now’s a good time to talk about what object oriented programming is, and what you’re looking at.

There are four basic concepts you have to understand to grasp object oriented programming. Different languages call them different things, but we’ll use the C++ names.

Objects

An object is a data structure that can contain attributes and methods.

Attributes

An Attribute is what the rest of the programming universe calls a variable. Attributes can be public or private, which determines whether outside objects can touch them directly or not.

Methods

A method is what the rest of the programming universe calls a function. Like attributes, they can be public or private, which determines whether outside objects can touch them directly or not.

Classes

This will take some explanation. In C, there are declarations called typedef. Typedef allows me to assign a new name to a variable type. If I wanted to make sure a given numeric variable has only one byte, I might declare it like this:

typedef uint8_t mynumber;

A uint8_t is a single byte, unsigned, so we can use all eight bits of it. You may see this again when we start writing bytes to ports. This typedef doesn’t declare a variable. It declares a type. If I want a variable of the mynumber type, I declare it like this:

mynumber george;
george=0;

Here I’ve declared the variable George, and set George to 0. Pretty straightforward stuff.

A class is like typedef for objects. It does not declare an object itself. It declares what an object will be like if one is declared (instantiated is the object-oriented equivalent).

In C++ (but not Java) I can do this:

// Include the libraries and classes we need for this program.
#include <stdint.h>
#include <iostream>


// Declare my class here
class myclass {
        // Declare our typedef
        typedef uint8_t mynumber;


        //Declare our private attribute of type mynumber.
        //No code outside the object can touch george.
        private:
                mynumber george;


        // Declare our public methods.
        // These can be called from outside the object.
        // We could have public attributes too.


        public:
                // Void means we're returning no values.
                // Note the cast, where we turn the integer input into a mynumber.
                void set(int input) {
                        george = (mynumber)input;
                }


                // Here we're returning an integer.
                int read() {
                        // Note the cast - we return the value of george,
                        // a mynumber attribute as an integer.
                        return (int)george;
            }
};


// Here is where we create an object of the type myclass. We call it
// myobject. We're declaring globally for the entire program.
myclass myobject;


// Main must return an int.
int main(){
        // Call the set method
        myobject.set(255);
        // Call the read method over here vvv
        std::cout << std::to_string(myobject.read());
}
Note

This example is written to compile and run in vanilla C++. Sketches don’t contain a main( ) because the Arduino app puts one in behind the scenes that calls setup( ) and loop( ) for us.

Looking at the code, you can see that it declares a class at the top: myclass. That class contains a typedef: mynumber, a private attribute (aka variable) George, which is of the type mynumber. George is declared private, so code outside the object isn’t allowed to change the value of George, or read George directly, or even know that George exists. This is the default behavior for anything inside a class, but it’s declared explicitly here to make it obvious .

The class also contains two public methods, read() and set(). Because these are public, they can be called from other code.

The next interesting thing is where we instantiate an object of the type myclass. I called it myobject. It’s exactly like declaring an integer or a char.

Once the object is instantiated, we can use it. Because it’s declared globally (outside any other function or object), we could use it from any function or object in the program.

We’ll use it from main(), because this is vanilla C++, but if you were using it in Arduino code, you could call it from setup() or loop(). The command myobject.set(255) calls the set method we defined in the class and instantiated when we declared myobject. The set() method can modify the value stored in George inside myobject, and it’s a public method, so 255 gets stored in George. The function call myobject.read() embedded in the cout (C++’s “write this data to the terminal” command, rather like Serial.print()) reads the value of George inside myobject. Again, it’s a public method, and it returns an integer, which we have to convert to a string, because unlike Serial.print, cout can only handle strings.

There’s a lot more to object orientation, and it gets brutally complicated as you go deeper into it. Arduino libraries are usually set up as classes. Arduinomorse is like that. The basic rules of object oriented C++ are: we can’t touch private attributes or methods; we can touch public attributes and methods; and in order to use a class, we must instantiate an object (declare a variable of that type) of it first. Knowing those rules will get you as far as we need to go in this book.

Hook Up the Hardware

For the Morse Code Practice Translator, as mentioned earlier, you need a 120Ω resistor and a speaker with wires you can connect to the breadboard. Wire the resistor from pin 21 on the ATmega1284P to the same row of tiepoints on the other breadboard. Make sure not to plug it into either of the + or - busses that are under it. It won’t hurt anything, but it won’t work. Wire one side of your speaker to that row of tiepoints, and the other lead to the - bus.

How the Hardware Works

It doesn’t get much simpler than this. There’s a method in the Arduino core called tone()which generates a tone of a given duration on a given pin. This does all the tone making for the arduinomorse library. One side of the speaker is connected to pin 21, because it’s handy, through the 120Ω dropping resistor so we don’t overload pin 21 (remember, outputs are limited to 40mA). Dividing 5 volts dropping over 128Ω (the resistor plus the speaker, as they are in series) we get about 0.039 amps, or 39mA. Just inside the limit. My speaker has a maximum rating of 0.5W (Watts), so if we multiply 0.039A times 5 volts, we get 0.195 Watts, less than half the limit for the speaker.

A Quick Word on Impedance

Speakers are inherently Alternating Current devices, and AC is... different. Here’s why. Where simple resistors offer only resistance to AC or DC circuits, capacitors and inductors (coils, like the ones that drive our speaker) also have reactance, which, in the case of the speaker, is a measure of how long it takes the magnetic field created to collapse and reverse. The voltage drop that a reactance produces is delayed from the corresponding drop in current, too.

Our speaker has a DC resistance of about 8Ω. This is its minimum impedence. When faced with an AC signal, its reactance will be higher in most cases. It won’t go lower. Our pin’s output impedance is about 125Ω (divide 5 volts by .040 amps), assuming the 40mA limit factors all the reactance in. That’s very close to the resistor-speaker value of 128Ω described above. You want the impedance of the speaker and the port to be about the same to transfer the most current. It’s not super-important for this circuit, as we don’t care about the sound quality of the audio, but it’s something to bear in mind.

The Code

// Morse Practice Oscillator
// Copyright 2015,2016 James R. Strickland
//-----------------------------------------------------------
// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General
// Public License as published by the Free Software
// Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will
// be useful, but WITHOUT ANY WARRANTY; without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program.  If not, see
// <http://www.gnu.org/licenses/>.
// ---------------------------------------------------
// Morse Code Practice
// This program pulls in morse.h from Mark Fickett's
// "arduinomorse" library and impliments a simple serial
// text to morse code practice sounder.
// ----------------------------------------------------
#include <morse.h> //Pull in the morse.h library.
#define PIN_SPEAKER 21 //define the correct speaker pin.
#define PIN_LED 1  //Define what pin our LED is on.
/* ----------------------------------------------------
   Create the C++ object "receiver" of the
   SpeakerMorseSender type.
   Set the output pin to PIN_SPEAKER, set the tone frequency
   to 440hz, -1 carrier frequency (it just adds noise), and
   set the morse code words per minute to 20. If you're
   new to morse code and trying to learn it, 5.0 might
   be a better value.
   If you'd prefer to read the Morse as LED flashes instead,
   Comment out the SpeakerMorseSender instantiation and
   uncomment the LEDMorseSender instantiation instead.
   ----------------------------------------------------*/
SpeakerMorseSender receiver(PIN_SPEAKER, 440, -1, 20.0);
//LEDMorseSender receiver(PIN_LED, 10.0);


/* Create the String object "FromSerial" because traditional
 *  C style string handling is painfully bad. */
String FromSerial = "";


/* The setup() function is one of the standard boilerplate
 * arduino functions. It executes once, so we put all our
 * configuration code in it. */
void setup() {


  Serial.begin (115200); //Set up the serial console at 115200 Baud.
  receiver.setup(); //tell receiver to set itself up.
/* Set the message to be sent to CQ. CQ is traditional
 * Morse shorthand inviting operators who hear it to respond. */
  receiver.setMessage(String("cq "));


/* Now send the message. Blocking means the sketch can do
 * nothing else while we're sending. */
  receiver.sendBlocking();
}


/* the Loop() function is one of the standard boilerplate
 *  Arduino functions too. It is called over and over again,
 *  forever. */
void loop() {
 /* Serial.available() returns the number of bytes available,
  *  if any, from the serial port. If that number is not zero.
  *  If that number is equal to zero, it is equivilent to
  *  logical false, otherwise is it logical true. We don't
  *  care how many bytes are available, just whether they
  *  are or not. If bytes are available, use Serial.read
  *  to read them into the FromSerial String object until they
  *  are gone. We assume the user won't send us strings that
  *  are too long. */
  if (Serial.available()) {
    FromSerial += (char)Serial.read();
  } else  
  if (FromSerial.length()) {
    receiver.setMessage(FromSerial);
    receiver.sendBlocking();
    FromSerial = "";
  }
//Remember, in the loop() function, we repeat forever.
}

How to Use the Sketch

Open the Serial Console and type the words you want to here in Morse code into the line next to the Send button, at the top. Then press the Send button or hit return. You should hear the familiar long and short beeps of Morse code from the speaker.

How the Code Works

Most of this project happens in the code, and there are two parts of it: the main sketch, and the library.

The main sketch includes morse.h from the Arduinomorse package. You can add packages manually, or you can click on Sketch ➤ Include Library and select the library you want from all the libraries the Arduino app knows about.

Next, the sketch defines PIN_SPEAKER(and PIN_LED). Note the lack of semicolons after these lines, and the hashtag in front. These are preprocessor macros.

The preprocessor is part of the C/C++ compilation system. It allows you to automatically make changes to the code when it’s compiled. It’s often used to make code more portable, so you can build it on multiple systems. In this case, the #define macros are simple search and replace macros. Every time the preprocessor finds the word PIN_SPEAKER in the code, it will replace it with 21.

In Arduino programming it’s very common to see a lot of macros, particularly in the guts of the bootloader and the core. Unlike a variable or a pointer, a macro takes no memory from the ATmega. None. Zip. The macro is processed at compile time.

Next, the sketch instantiates receiver as an object of the SpeakerMorseSender class. Remember, receiver is the object, SpeakerMorseSender is the class.

Next, the sketch instantiates the object FromSerial of the class String. The Arduino String object has a lot of useful methods and is easy to use. I called the object FromSerial, because it will be getting data from the serial console. More on that further down.

In the setup() function , we tell the sketch it will be communicating with the serial console with Serial.begin(57600).

Note

Serial.begin(115200) sets the RS232 speed to 115200 baud. Make sure your serial console is set to the same speed, or the serial console and the Cestino won’t understand each other. I use 115200 baud for the remainder of this book.

Once serial is set up, we call receiver’s method setup(). Setup is a method of the SpeakerMorseSender class that tells the object to set the speaker pin as an output. I know this, because I poked through the library code and saw it.

Next, we call receiver’s method setMessage(). We set the message to “cq”, which is Morse code shorthand for “Anyone who can hear this, please respond.” Notice that we cast “cq” which is a character array by default, into a String object, which is what the arduinomorse library wants.

In the next command, we call receiver’s method sendBlocking(), which tells receiver to go ahead and beep out the message we sent.

Why are we sending a message in setup? Because it’s handy to know that the speaker is connected properly and everything is working when the sketch starts.

Note

It’s been said that the telegraph was the 19th century’s Internet. Morse code was invented in the 1830s (not coincidentally around the same time Ohm’s Law was developed) and used heavily for over a century. Just like Twitter has its own slang—lol, rotfl, ttyl, and so on—Morse code has traditional slang, too, and for the same reason. It’s quicker and easier to send.

Blocking just means that the sketch can’t do anything else while it’s beeping out Morse code. The library can send nonblocking, but we don’t need it in this case.

Once we enter the loop() function of the sketch, one of two things happen over and over again. If the Serial.available() method returns anything but zero (logical false) we read one character and add it to the FromSerial String object. Otherwise, if the FromSerial.length() method returns anything but zero, we set the message, send it blocking, and clear the FromSerial String.

If there is no data waiting in the Serial object (Serial.available() returns 0 or logical false) or if FromSerial.length() returns 0 or logical false because the FromSerial String object is empty, we do nothing, and loop repeats forever, until we load a new sketch or turn off the power.

Note

Boolean values are stored in 8 bits of data, even though they only need one. The way they’re evaluated is that if every bit is 0, then the Boolean is false. Otherwise it’s true. This is why I can throw integers, like FromSerial.length( )’s return value, at boolean logic and have them evaluate correctly. The canonically correct way would be to see if FromSerial.length( )==0, but this works.

Summary

In this chapter, we set up an external Arduino as an ISP and loaded a bootloader onto the Cestino. After that, we tried two fairly simple sketches on it to prove that it works.

Credit Where Credit’s Due

Once again, the Arduino LLC did most of the heavy lifting in this project. I added the Burn Bootloader Preflight Check tool. Obviously, Mark Fickett’s arduinomorse library saved me a ton of coding.

Further

Like Chapter 2, the further part of this project is really the rest of this book, in which you use the Cestino as a tool to do the remaining the projects. The Morse Code Practice Translator, by contrast, could go much further.

Out there on the Internet, there exist several other Morse code libraries. Unlike arduinomorse, some apparently have the ability to time and translate incoming Morse code. Given that and an extra button (or a proper Morse code key) wired to a separate pin, one could have two-way conversations with the Arduino in Morse code. A web search will turn up a number of resources.

The ability to send or receive and translate Morse code might have huge possibilities in the ham radio world. Although code is not required for some licenses anymore, it is still used.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.197.95