Category Archives: Arduino

Getting Started with the ESP32 S2 Mini

Getting Started with the ESP32 S2 Mini

The ESP32 S2 Mini i s a small development board based on the ESP32-S2FN4R2 chip. The ESP32-S2 Mini by Wemos can be used as an Arduino, which is what this post covers. It can also be programmed in other ways, including with MicroPython, CircuitPython and with the chip manufacturer’s (Espressif) own software development kit.

Capabilities

The board can be used as an Arduino, although as with all different Arduino boards, it will have quirks that will mean some libraries will need special versions. This is the same as different boards within the Arduino family to a degree, and is often due to a mixture of hardware features being on different pins, or software maturity. It is worth pushing through these issues for the benefits the chip brings over a standard Arudino Uno or similar.

  • Processor Speed – 240MHz (32bit)
  • 3.3V Power and digital outputs, but 5v tolerant digital input pins (you can send it 5V signals without harm)
  • USB-C Connector
  • Wifi capable (can be turned off if not needed)
  • 4MB Flash (for programs, and for storing resources such as images, html files or sounds)
  • 2MB of RAM
  • 27 I/O pins
  • 12 Digital I/O pins
  • 18 Analogue Input Pins
  • 2 Proper Analogue Output Pins (not PWM)
  • 27 PWM Capable Pins
  • 27 Pins Serial Capable
  • Multiple I2C and SPI Busses

Note this specific chip doesn’t support Bluetooth (unlike other related products which sometimes do).

Reference Materials

Handy for looking up electrical specifications, the chip datasheet can be found here, and there is information on Arduino compatibility here.

The development board manufacturer has reference materials here and Arduino getting started here.

Pinout Diagram

Adding the Board to the Arduino IDE and First Test

  • Launch the Arduino IDE (I’m using version 1.8.9 on Linux).
  • Go to Tools>Boards>Board Manager, and type in “ESP32”.
  • Select and install Version 3.1 (3.1 is the newest at the time of writing – version 3.0.5 didn’t work properly for me) “esp32 by Espressif Systems” (not “Arduino ESP32 Boards”).
  • If “esp32 by Espressif Systems” doesn’t show up in the list when you search, go to File>Preferences and add the following text to the “Additional Boards Manager URLs” text box. If there is already text in there, you need to add it to the end, after a comma and a space.

The text to add : https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Returning to the Boards Manager as above, you should now be able to see the “esp32 by Espressif Systems” option when you search.

  • From the Tools>Boards sub menu, pick the option LOLIN S2 MINI.
  • Open the Blink example from File>Examples>01.Basics>Blink.
  • Plug in the board using a USB-C cable.
  • Press and hold the button on the board labelled “0”, and briefly press the “Reset” button, wait another two seconds and then release the “0” button.
  • Select the board in the Tools>Port menu.
  • Click the “Upload” arrow.
  • Once the upload has finished, it might show an error, but regardless, press the “Reset” button on the board. The onboard LED should start blinking.

If you’re on Linux, you may need to set up USB permissions as per the instructions here.

If you have any issues, try a different USB cable. The first one I tried didn’t work properly (some don’t have all of the wires inside them).

A More Interesting Example

The most useful starting point is the provided example found at File>Examples>WiFi>WiFiAccessPoint. This example turns the board into its own WiFi network (separate to the house network). You can use your phone or laptop to connect to this network, and then load one or more web pages served up by a mini web server on the board. I often use this to provide an easy control interface (buttons and feedback). It is also possible to do firmware updates over WiFi, which can be very useful when the controller is buried deep in a machine. Obviously, make sure you use a password on the WiFi to stop other people messing with things.

Upload the WiFiAccessPoint example onto the S2 Mini board. I’m not certain why, but I had to completely power cycle my S2 Mini before the WiFi appeared.

Plug the S2 Mini into a USB port on your computer and open the serial monitor. Using your phone or laptop, connect to the WiFi access point that has the name yourAP. The default password is yourPassword. You should see information appear in the Serial Monitor, including the “host” IP. This is probably 192.168.4.1. Go to this address in your browser by entering http://192.168.4.1 or just click that link if you have this page open on the computer you connected to the S2 Mini with.

You should be presented with a simple webpage that has two lines of text, each with a link in it. The two links turn the LED on the board On or Off. Clicking them causes more activity in the serial monitor.

A Couple of Clone Arduino Linux Issues

A Couple of Clone Arduino Linux Issues

The serial port appears for a single second, and then vanishes before you can upload any code.

This has been happening to me with Pop OS, but apparently also happens with other Ubuntu variants. I can’t believe what the cause is, but if you check dmesg and you will possibly find the following occurring :

[   98.044600] usb 3-2: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice=81.33
[   98.044606] usb 3-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[   98.044607] usb 3-2: Product: USB Serial
[   98.046052] ch341 3-2:1.0: ch341-uart converter detected
[   98.046409] usb 3-2: ch341-uart converter now attached to ttyUSB0
[   98.608979] input: BRLTTY 6.4 Linux Screen Driver Keyboard as /devices/virtual/input/input41
[   98.887664] usb 3-2: usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1
[   98.888541] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0

What we see happening is the OS finds the newly plugged in CH340 based serial device on your board and creates a new serial port, in my case, ttyUSB0. Excellent. But then, along comes “BRLTTY”. BRLTTY has decided it knows what this device is, removes the serial port and turns the device into an input / keyboard device. BRLTTY apparently knows best and claims all devices with the manufacturer / product ID of a USB to UART adapter chip, that is absolutely not always the product they think it is. This is really poor default behaviour, especially as this all happens silently. Apparently BRLTTY is accessibility software for the blind that is installed by default.

To solve the issue, assuming you’re not blind, simply type “sudo apt remove brltty” (without quotes) at the command line and it will be uninstalled, making the issue go away.

Not in Sync

The not in Sync error, where you get a repeated message such as the following :

avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00

… is an old one with many causes. One cause now seems to be that if you use a clone device, the Arduino IDE refuses to talk to it by default. The solution might be to change the “Processor” in the Tools menu to “ATmega328P (Old Bootloader)”. This would apply to boards such as Unos and Nanos. This might actually also apply to older genuine Arduino Boards.

As you might guess, I’ve had a slightly frustrating day. All I did was try to load a program into a clone board someone gave me the other day.

The Basics of Logic Circuits – Part 1

The Basics of Logic Circuits – Part 1

An Introduction

As a child I had an interest in electronics. I took options at school which taught me the basics, but found that a few small details were omitted which made it slightly more difficult to move from theory to practice. Following a recent discussion with my brother about how we thought it would be best to introduce electronics to a beginner and move through to designing and building your own circuits, I decided to write something to hopefully help other people in the same position as my 15 year old self.

Useful Parts for the Following

  • 74HC00 – Quad 2-input NAND gate
  • 74HC04 – Hex inverter gate (NOT)
  • 74HC32 – Quad 2-input OR gate
  • 74HC08 – Quad 2-input AND gate
  • 2N7000 – MOSFET
  • Pushbutton
  • LED
  • 220R Resistor
  • Breadboard
  • Power source?

Basic Boolean Logic

As a tool for introducing electronics in more general terms, I’m going to introduce logic and logic chips. In electronics, logic is usually based on the theory of using voltages to represent two states, “TRUE” or “FALSE”, sometimes called “HIGH” and “LOW” (in reference to the voltage). When the voltage is high, and the signal is considered to be present, this is a TRUE. Multiple TRUE and FALSE signals can be used together representing a set of inputs to be analysed to give specific outcomes in specific input scenarios by applying various logic operations. Even with basic logic rules, complex systems can be built.

The three most basic logic operations commonly seen in electronics are “AND”, “OR” and “NOT”. These are implemented physically as “gates” (e.g. “you need an AND Gate in your circuit”), which it is common to find several of in one microchip. The most conceptually simple gate is the NOT gate, which takes an input signal, and inverts it before outputting it. This means that when applying a logic TRUE to a NOT gate, it will produce a logic FALSE at the output pin and vice versa. The OR gate provides a logic TRUE when either one, the other, or both of its inputs are TRUE. Finally, the AND gate produces a logic TRUE only when both inputs are TRUE. Any time the output is not TRUE for any of these gates, it will be FALSE. The following table shows all combinations for two inputs named Input A and Input B. It is possible to have AND and OR gates with more inputs, although the same result can be achieved by using multiple gates consecutively and feeding the output of one into the input of another. Note that as shown in the following table, the NOT gate has a single input. Within the table, the NOT gate has been assumed to be connected to Input A (and duplicate second rows have been omitted for clarity).

Input A Input B AND OR NOT
FALSE FALSE FALSE FALSE TRUE
FALSE TRUE FALSE TRUE
TRUE FALSE FALSE TRUE FALSE
TRUE TRUE TRUE TRUE

Equivalent Circuits

The various logic circuits can be considered as behaving in a similar manner to the following conventional electrical equivalents. These equivalents use switches to achieve the same behaviour, where the bulb represents the output.

AND – Two Switches in a Row

OR – Two Switches in Parallel

NOT – A switch in Parallel with the Load

When the switch is pressed, the load is bypassed as the path of least resistance is through the closed switch. This means that when the switch is closed (TRUE), the LED is off (FALSE) and vice versa. The resistor R1 is included so that the switch is not a dead short over the battery. The battery voltage was increased to 5V to make the circuit more realistic in that the LED would be dim (or go out) if the 2V supply from the two previous circuits was used.

If you are unsure why this circuit acts as a NOT, consider that the resistance of a typical 10cm wire and switch might be 0.0005 ohm. Current follows alternative paths inversely proportionally to the resistance. If two paths are of equal resistance, the current will divide equally between both routes. If one resistance is 10 time greater than the other, 10 times more current will flow through the LOWER resistance path. As the LED has an effective resistance tens of thousands of times greater than the wire (if not more) effectively all the available current will go through the wire and switch rather than the LED. When the switch is released (goes open) the resistance of that path becomes huge (it might as well be infinite) and so all available current goes through the LED as it is now the path of least resistance. Much more detail can be given regarding how the resistance of an LED changes depending on voltage, about the resistance of the circuit and about the resistance of individual parts of the circuit etc. but very quickly this gets too detailed and distracts from the purpose of this example!

Just Draft Notes from here on in. Also, check that a 1k resistor is suitable for the circuit I drew. OK – I’ve checked the 1k and it looks OK (but I’d prefer to test the circuit) It results in less than 1.4mA current in the LED and not more than 5mA into the Base? something like that. A bigger resistor might be better, say 2 or even 3k.

Using Transistors Instead of Switches

There are two main types of Transistors, NPN and PNP. Effectively, the NPN produces switches on when a current is provided to the Base pin, while a PNP switches off when a current is provided to the Base pin. I remember the difference between the two symbols by telling myself that NPN stands for “Not Pointing iN”, with reference to the arrow in the symbol. The two symbols are as follows.

AND – Using Two NPN Transistors

In the preceding example the Base pins on the transistors are shown with the Base pins protected by 1k current limiting resistors (R1 and R2). In a real application, these inputs would be connected to something like the output pins of a microcontroller. The LED is also in line with a 220R current limiting resistor. To implement this circuit, you might use the common BC547 NPN transistor. This would be suitable for use with, for example, a 5V Arduino Uno. The following schematic shows how this might be implemented. Similar methods can be used for the OR and NOT implementations which follow, but this post does not go into detail regarding using transistors as the primary intention is to explain the use of Logic chips. I might return to the subject of transistors at a later date.

OR – Using NPN Transistors

Supplying current to either (or both) Input A or B will provide a current path from the LED to ground, completing the circuit and implementing our OR logic.

NOT – Using a PNP Transistor

To implement the NOT logic using a transistor, the easiest solution is to use a PNP transistor instead of the NPN used in the previous two examples. As noted, this type of transistor closes when current is provided to the Base. Note the different location of the arrow within the transistor’s symbol. The common PNP equivalent of the BC547 is the BC557.

In reality, within integrated circuits, the logic implementations are more complex to allow greater flexibility and a more well rounded product. The following is an extract from a Texas Instruments datasheet for the 7408, showing the individual transistors within each gate of the logic chip. The design is beyond me… especially as I’ve never seen a transistor with 4 legs.

Additionally, it is also possible to implement logic using “Relay Logic”, but that is a topic for another day.

Symbols

The symbols for the AND, OR and NOT gates are shown above. Note the small dot on the NOT gate – without the dot the triangular symbol would represent a buffer, which does not modify the output logic and simply passes the input signal to the output. The dot symbolises that the output should be inverted. This dot can be also added to other gates to mean that the output should be inverted. In the case of the AND and OR gates, this produces the NAND and NOR gates.

Note that schematics within this post were drawn using Fritzing – a free circuit designing program for Linux, MacOS and Windows.

Getting Started With Phil’s Sonoff Firmware

Getting Started

When you power on your smart relay (which is loaded with my Firmware) for the first time, an LED will light immediately – when you see this, press the button “L1”, or the only button if there is just one button and hold it for 5 seconds (or a bit longer to be on the safe side).

If you get a laptop with Wifi and look for available networks, you should see a new network starting with “Sonoff”. Connect to this – the default password is “password”.

Write down the name of this network as we will need it later.

Once connected, open a web browser and go to the following URL :

http://192.168.4.1/set?data=1111

This should turn on the relays (and indication LEDs). Now go to the following URL :

http://192.168.4.1/set?data=0000

This will turn all relays off again.

Connecting to the house WiFi

To connect your relay to the house wifi, continuing from above (with a computer connected to the relay’s own “Sonoff” wifi network), carefully enter the following URL, substituting <ssid> for the name of your wifi network.

http://192.168.4.1/wifi?ssid=<ssid>

For example, if your wifi network is called “spaceship” then you would enter http://192.168.4.1/wifi?ssid=spaceship

Next, to tell the relay the password for your wifi network, carefully enter the following, substituting <passwd> for your wifi password :

http://192.168.4.1/wifi?password=<passwd>

If you now power cycle the relay (do not press the button), it should automatically connect to your wifi network and be available to all devices on the network. Note that if your network name or network password contains symbols which are not valid in a URL, you might need to use escape characters, change the wifi details, or give up.

Using the wifi network name you wrote down earlier, try the following, replacing <relayname> with the network name you wrote down :

http://<relayname>.local/set?data=1010

and this :

http://<relayname>.local/set?data=0101

If these do not work, try the same, without “.local”.

From the Terminal

From the terminal on a Mac or Raspberry Pi, try typing the following command

wget -qO – http://<relayname>.local/set?data=1111

This command can be called from inside Linux style bash scripts. Similar things can be done from within Python.

Tracking the Temperature

For the last long while, I’ve been tracking the temperature in our conservatory. This started when we had a pigeon living in there and I realised it was getting very warm during the day. Firstly, I started tracking the temperature, then I added a fan to an existing catflap to help cool the area, (then I removed the pigeon) and ultimately, the system now runs on an ESP8266 which monitors the temperature, switches the fan on for low and high temperatures (drawing air from the more thermally moderate house), provides a web interface for control and generates a status webpage using dynamically created SVG images.

Temperature Plot
Temperature Plot

An Orange Pi Nano computer is scheduled to fetch these images over the internal network every now and then, and uploads them to my website. I have been also saving the resultant 24 hour plots for each (most – I’ve had a couple of power and or internet outages) day.

The current status (near live) can be found here.

Historic data is crudely stored here (I need to add pages, possibly automatically because I’m lazy. I think I worked out how at the time (show number ranges x through y, multiples… something like that. Perhaps need to learn how to pass parameters to php as I don’t really do internet stuff), but never implemented it.

In the future, I plan on modifying the code to reduce the work done by the ESP8266 to just fan control and temperature logging, with more of the intelligence / image generation offloaded to the Orange Pi Linux SBC. I will then consider creating more sensor nodes, using sleep functions to minimise power consumption to a level suitable for battery and / or solar power and ultimately, put other sensors around the house and in the garden shed.

Temperatures in the house might enable me to control our central heating boiler in a more intelligent fashion than it already is, while the garden shed would be a good source of the ambient temperature in our location (handy for passive cooling with ambient air for example, using fans fitted to the fresh air bricks in the house).

Custom Hard Disk Cooling

Update : I’ve realised that changing the pull up resistor to a pull down resistor means that the circuit will react better if the fan 12V is applied before the Arduino power supply is activated. As such, I’ve moved my resistor so that it is now between the gate pin and ground.

Having a bit of spare time, I decided to transfer a load of files from my previous computer (a Mac) to my new computer (Linux). As I had a lot of data from a number of hard disks to move, I decided the best method would be using an external eSATA drive. Thankfully, due to a stalled home build SAS project I started a few years ago, I have a couple to hand. The are branded as SUUNION SUBE3ZW enclosures, the “E” being optional and meaning they support eSATA. Helpfully they come with an internal SATA to eSATA expansion slot adapter and my motherboard has a feature in the BIOS that lets you turn hot swapping on for a SATA port. Without the latter, I’d have needed to power down my computer every time I wanted to switch in a different disk. These SUUNION enclosures have almost no internet presence, but were really cheap about 7 or 8 years ago when I bought them.

SUBE3ZW Enclosure
SUBE3ZW Enclosure

While transferring data, I noticed in the S.M.A.R.T data for the drive that it was getting quite warm and had reached 50°C. I looked up the temperature ratings for the drive in question (a 1.5TB Seagate Barracuda) and discovered they were rated to a maximum temperature of 50°C… oh dear. It seems that it isn’t great to run some (7200rpm) disks in fan-less enclosures.

Initially I grabbed my home made soldering air filter (120mm computer fan, connected through an inline power switch to a 12v wall-wart) without the filter to cool it down, but since I had time to kill waiting for the file transfers and the fan was quite loud considering my girlfriend was trying to work in the same room, I started looking into adding some speed control.

The Circuit

Parts used:

  • 1x Arduino Pro Mini (anything similar will do, including an UNO – note that devices with different main chips will have different PWM requirements and the code will not work without changes).
  • USB to UART board, like this one.
  • 1x 2N7000 MOSFET – an excellent all-rounder MOSFET.
  • 1x 1N4007 Diode – massively over-specified, but I have a bag of them and they cost very little. Any similar diode will do (I suspect anything from the 1N400x range is fine).
  • 1x 10k Resistor (0.5W).
  • Breadboard – the circuit could be built on protoboard for a more permanent solution.
  • Some wire, suitable for use in breadboard.

Breadboard Layout of Fan Controller
Breadboard Layout of Fan Controller

Three things to take care of :

  • Do not connect the 12V supply to the microcontroller – this will damage it, and potentially any connected computer.
  • Note the pins on the left of the Arduino are reversed on some clones – my device has the pins in the opposite order to those shown in the drawing above. If your Arduino matches the drawing above and you are using the same USB adapter as I am, your adapter should be face down into the table. If your Arduino and USB adapter are both identical to mine, the adapter should be face up.
  • Ensure the USB adapter power jumper is set to 5V if you are using a 5V arduino. The circuit should also work with a 3.3V Arduino (the minimum gate trigger voltage for the 2N7000 MOSFET is 3V), although ensure all voltages are correct.

The following is a rough schematic – all ground points need to be linked (as per the breadboard layout).

Fan PWM Controller Schematic
Fan PWM Controller Schematic

The 10k resistor (R1) is a pull down resistor and is needed to control the input to the MOSFET – without this the MOSFET might get very hot and fail if the Arduino is removed or if the connected pin is set as an input. The resistor is best located as close to the MOSFET gate pin as possible. The Diode (D2) (yes, the numbering system is wonky) dissipates the back EMF generated by the fan when the supply is cut. The MOSFET (Q3) switches the 12V supply (on the low side of the fan) based on the PWM signal from pin 10 on the Arduino, while effectively isolating the Arduino from the 12V and preventing damage. On its own, the Arduino would not be able to provide 12V, and can not provide the 180mA required by the fan I am using. The 2N7000 MOSFET is actually able to switch voltages up to 60V, although that is more than my fan can handle.

Once I had programmed the Arduino, I disconnected the DTR pin from the USB adapter to prevent my computer from resetting the Arduino constantly – this will not be possible so easily if you’re using an Arduino Uno. The trick I like to use to do this with an Arduino Pro Mini is as follows :

  1. When soldering headers onto the Arduino Pro Mini, replace the supplied male header with a female header – this makes programming the boards much easier as the USB adapter has male headers.
  2. Once programming is completed and you do not want the board to reset when a serial connection is established, place a 5 pin female header with extended pins (wire wrap / pass through style) between the Arduino and the USB adapter, taking care that the missing pin is the DTR (“GRN”) pin.

Note that it is still possible to program the board in this condition if you carefully press the reset button at the exact right moment. Also note that I actually use a 6 pin header with one pin trimmed off (because it reminds me what the header is for when I see it lying on my desk and I don’t throw it away).

Disable Reset
Disable Reset

The Fan

I’ve used a small 40x40x20mm fan that I had in a cupboard. Other fans will be fine, although note that at these high PWM frequencies, I did have some difficulty with one cheaper fan where it was struggling to start.

To help with this, I’ve modified my Arduino software to give the fan a short burst of maximum speed (a fraction of a second) whenever the fan speed changes to help ensure the fan is running – while there is still a PWM duty below which the fan will not run, I have found that this specific fan generally runs down to as low as 50/255 (~20%) of full. Note the PWM duty does not correspond to fan speed – most of the variation available is between 200 and 255 (~80% to ~100%).

It is recommended that you put a switch in the 12V supply so that it is possible to turn off the fan easily. An improvement might be to take the pull up supply from the 12V using a regulator to generate 5V (for the whole circuit). Care should be taken to not back feed the computer’s USB with a slightly different 5V supply. There is a built in regulator on the Arduino Pro Mini which could be used for this, where 12V could be provided to the “RAW” pin, although 12V is the maximum recommended voltage for this regulator and it might get warm with sustained use. This would be a good option if you were also measuring temperatures using the Arduino in another application.

The Stand

A quick and easy way to make an adjustable stand for a fan is to use a piece of stiff wire, bent into shape through two of the fan’s screw holes. I’ve used a piece of stainless steel welding wire as can be seen in the following photograph.

Fan and Stand
Fan and Stand

The wire is in one piece and crosses the front of the fan between the two screw holes (on the other side of the fan from the camera). Pliers will make bending the wire easier.

Arduino Software
/******************
 * Arduino High Frequency PWM Fan Controller Code
 * https://elephantandchicken.co.uk/stuffandnonsense
 * Circuit :
 * Connect the gate of a 2N7000 to arduino pin 10.
 * Connect a 10k Resistor between the gate and 5V.
 * Connect the source pin to ground.
 * Connect a 1N4007 diode between the drain pin and 12V with the band facing 12V.
 * Connect a fan between the 12V rail and the drain pin.
 * Remember to connect the grounds for the 12V and 5V circuits!
 * Do not mix 12V and 5V!
 * If in doubt, details of the circuit and software for controlling from linux
 * are on my website
 *******************/

int fan = 10; // set fan output pin
int fanspeed = 255; // start full speed
// for SerialEvent
String inputString = "";
boolean stringComplete = false;

void setup() {
  // set the fan pin as an output
  pinMode(fan, OUTPUT);
  
  // adjust the PWM speed to make it fast enough that you can't hear it
  // see : https://playground.arduino.cc/Main/TimerPWMCheatsheet
  TCCR1B = (TCCR1B & 0b11111000) | 1; // hard coded for pins 9 or 10
  
  // Start serial - doesn't need to be very fast
  Serial.begin(9600);
  Serial.println("\nPWM Fan Controller Started");

  // For safety, as we don't know what is happening yet, turn the fan onto full
  digitalWrite(fan, HIGH);
}

void loop() {
  if(stringComplete){ // We've recieved a message
    // reset the serial variables ready for the next message
    String msg = inputString; // store locally so serialEvent can get back to capturing input
    inputString = "";
    stringComplete = false;
    
    if(msg.startsWith("s")){ // "set" command
      if(fanspeed!=msg.substring(1).toInt()){ // if the requested speed is different...
        fanspeed = msg.substring(1).toInt(); // update the fan speed
        digitalWrite(fan, 1); // these two lines help with a stalled fan...
        delay(50); //             by ramping the speed to full with no PWM for a short period
        analogWrite(fan, fanspeed); // set the new PWM duty
      }
      Serial.println(fanspeed); // confirm the new speed to the host
    }else if(msg.startsWith("c")){ // "check" command
      Serial.println(fanspeed); // the host has asked what PWM duty we're currently using
    }
  }
}

void serialEvent() {
  // Standard serial code from "SerialEvent" example
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n' || inChar == '\r') {
      stringComplete = true;
    }
  }
}
Linux Software

Due to the limitations of my knowledge in various languages, I’ve used a mixture of bash and python as well as an existing piece of software to achieve what I wanted. My objectives were to continually monitor the external hard disk temperature, and set the fan speed based on this temperature. First things first, I used the “Disks” utility on Ubuntu to identify the external disks location – for exampe : /dev/sdc

The path “/dev/sd*” (where * is a letter of the alphabet) should exist for each connected disk, the similar files with a number on the end as well represent individual partitions and we are not concerned with these at the moment.

Next identify the serial port – with the adapter connected, type “ls /dev/ttyUSB*” at the command line. If you’re lucky, you will get a single result called “/dev/ttyUSB0” or similar. Note this can and does change, especially when you’re plugging and unplugging USB adapters, so you might need to re-check. If the previous command doesn’t return anything, try “ls /dev/tty*”. This will return a long list – ignore all entries which are just “/dev/tty#”, “/dev/ttys#” or “/dev/ttyprintk” where “#” is a number. Look at what else is there… unplug the adapter and run the command again. What is different? Plug the adapter back in again – does it re-appear? Whatever appears and disappears when you plug and unplug the adapter is the serial port you are looking for. As mentioned, the number might change as you are messing around.

Make a note of the disk path and serial port path. Mine are “/dev/sdc” and “/dev/ttyUSB0”.

Software which might need installing :

  • watch (sudo apt-get install watch) – allows you to run a command every n seconds
  • hddtemp (sudo apt-get install hddtemp) – reports the identified disk’s temperature
  • python (sudo apt-get install python) – programming language, probably already installed
  • pyserial (pip install pyserial) – a python library to work with serial ports

Create a folder and move into it (to do this in the command line, use mkdir HDDTemperature && cd ./HDDTemperature to create a folder called HDDTemperature at your current location). Create three plain text files called hddFanControl.sh, hddFanControl.py and run.sh using your favourite text editor. Enter the following scripts into each respectively :

# Script to check a hard disks temperature, and send a fan speed over serial
# Usage :
# run.sh /dev/sd* /dev/ttyUSB*
# Ensure run.sh, hddFanControl.sh and hddFanControl.py are all in the current
# active directory.
# Note you need permission to access both the hdd and the serial port
# Note you'll need to disable reset on the MCU
# Serial fan controller should accept speed settings in the format s[0-255]
# where [0-255] is the pwm value between 0 and 255. Note most speed control
# is between 200 and 255, and often a fan needs 255 to start (due to the high
# pwm frequency (I'm using 31khz I think - there aren't many options on an 8
# bit AVR, just 60khz and 30khz which don't create noise. 60khz struggled to
# start the motor. AVR code I used to set the pwm speed was :
# TCCR1B = (TCCR1B & 0b11111000) | 1;
# and I'm using pin 10 (this command would also work for pin 9)
# be warned that messing with these pwm settings impacts other timing commands
# 
# https://elephantandchicken.co.uk/stuffandnonsense
# 12/12/2018

# hdd location
VARHDD="$1"
# serial port
VARSER="$2"

TEMPERATURE=`hddtemp $VARHDD | grep -oh "..°C" | grep -ohE "[0-9]{1,4}"`
echo "Selected disk temperature is $TEMPERATURE°C"

python ./hddFanControl.py $VARSER $TEMPERATURE
# Script to check a hard disks temperature, and send a fan speed over serial
# Usage :
# run.sh /dev/sd* /dev/ttyUSB*
# Ensure run.sh, hddFanControl.sh and hddFanControl.py are all in the current
# active directory.
# Note you need permission to access both the hdd and the serial port
# Note you'll need to disable reset on the MCU
# Serial fan controller should accept speed settings in the format s[0-255]
# where [0-255] is the pwm value between 0 and 255. Note most speed control
# is between 200 and 255, and often a fan needs 255 to start (due to the high
# pwm frequency (I'm using 31khz I think - there aren't many options on an 8
# bit AVR, just 60khz and 30khz which don't create noise. 60khz struggled to
# start the motor. AVR code I used to set the pwm speed was :
# TCCR1B = (TCCR1B & 0b11111000) | 1;
# and I'm using pin 10 (this command would also work for pin 9)
# be warned that messing with these pwm settings impacts other timing commands
# 
# https://elephantandchicken.co.uk/stuffandnonsense
# 12/12/2018

import time
import serial
import sys
from math import log

# How aggressive to make the fan curve? 0.4 is normal, 0.1 ramps up quickly
# at the start then levels off, 1 is linear (pwm duty, not cooling), 2 mainly
# ramps at the top end (would be basically off until the temp was at the top)
fanCurve = 0.4 

Temperature = int(sys.argv[2])
maxTemp = 50
minTemp = 30
tempRange = maxTemp-minTemp

tempLift = Temperature-minTemp

if tempLift <= 0:
	pwmDuty = 0
elif tempLift >= tempRange:
	pwmDuty = 255
	print "\nWarning! Hard Disk is hot!"
	print "Disk is currently : " + str(Temperature) + " degrees C"
else:
	var1 = (tempLift**fanCurve)
	var2 = (tempRange**fanCurve)
	pwmDuty = int(255*var1/var2)
	print "\nCurrent Temperature : " + str(Temperature)
	print "Current Target PWM setting : " + str(pwmDuty)

ser = serial.Serial(
	port=str(sys.argv[1]),
	baudrate=9600,
	parity=serial.PARITY_NONE,
	stopbits=serial.STOPBITS_ONE,
	bytesize=serial.EIGHTBITS
)

ser.isOpen()

#flush with an empty line
ser.write('\n')
time.sleep(0.1)
ser.flushInput()

# moved the following into the mcu
#if pwmDuty > 0:
#	# make sure we are not stalled
#	ser.write('s255\n')
#	time.sleep(0.1)

#check current setting
ser.write('c\n')
time.sleep(0.1)
out = ''
while ser.inWaiting() > 0:
        out += ser.read(1)
if out != '':
        print "\nMCU previous PWM was : " + str(int(out))

#send pwm setting
ser.write('s' + str(pwmDuty) + '\n')

# pause and see if there was a response
time.sleep(0.1)
out = ''
while ser.inWaiting() > 0:
	out += ser.read(1)
if out != '':
	print "MCU current PWM is : " + str(int(out))

ser.close()
exit()
# See comment in hddFanControl
# https://elephantandchicken.co.uk/stuffandnonsense
# 12/12/2018

watch -n60 ./hddFanControl.sh $1 $2

Back at the command line, enter the following three commands to convert the files into runnable software :

chmod +x ./hddFanControl.sh

chmod +x ./hddFanControl.py

chmod +x ./run.sh

To run the software, ensure that the Arduino is powered and connected to the computer through the USB adapter, then apply power to the fan. The fan should start at maximum speed.

You’ll need the disk and serial port paths from above to run the software, once you have them and have checked they are correct, enter the following (but using your hard disk and serial port) :

sudo run.sh /dev/sdc /dev/ttyUSB0

If everything works correctly, you should see something like the following, which will update every 60 seconds :

Screenshot
Screenshot

To stop the program, press Ctrl-C. Once you’re finished with the fan, power down the 12V fan supply and the Arduino.

Changing Parameters

To change the temperature update frequency, you will need to edit the file run.sh. The interval between measurements is represented by the 60 in “-n60” and can be replaced by other durations in seconds. To change the interval to be two minutes, run.sh would need to be changed to :

# See comment in hddFanControl
# https://elephantandchicken.co.uk/stuffandnonsense
# 12/12/2018

watch -n120 ./hddFanControl.sh $1 $2

All other parameters which can easily be modified are contained within the python file hddFanControl.py and allow the “normal” temperature range, and temperature/PWM response curve to be modified. Normal temperatures are defined by the variables maxTemp and minTemp (set to 50 and 30 respectively in the provided code). When the measured temperature is outside of this range, the fan duty will be pegged at either 0% (30°C or less) or 100% (50°C or more). These values can be modified the shift the operating temperature range if needed.

The temperature/PWM response curve is modelled as the temperature above the minTemp raised to a power (a variable called fanCurve). By adjusting the power, the characteristic of the curve can be adjusted. By default I am using a power of 0.4, which works well for my use case. The following plot shows the impact of varying the value of fanCurve.

PWM Plot
PWM Plot

Adjusting the value allows the user to modify how early or late the % duty increases. Note that this only relates to the PWM duty and not fan speed. I have generally found that most of the variation in fan speed is observed in the last 25% of PWM duty.

Note that modifying the fanCurve variable is the best way of adjusting the balancing temperature of a specific state. Using 0.4, I was able to achieve a stable 37°C disk temperature, which was considered satisfactory, and comparable to the temperatures of my internal hard disks.

Conclusions

If you’re wondering, the file copy still hasn’t finished. (Update : it finally has).

ReadyAVR-64 – A board without documentation

I recently purchased a Atmel ATmega128 breaout board designed by LogiFind, called the ReadyAVR-64. The company seems to be imitating Mikroelektronika with their naming conventions and produce intermediately priced educational boards. They provide some examples and software, oriented around Windows as a host platform for most of their boards. I have a couple of examples for there wares, from the giant “EasyAVR128” to the more basic “ReadyAVR-28” (which I plan to swap a ATmega328 into – they do a board with one pre-installed, but it costs more). Currently, the documentation download link on their website for their ReadyAVR-64 board seems to be broken.

Despite being a blue PCB in all adverts etc. the board I received in the post was green. I had some minor postage issues, with my package been returned to sender for an unknown reason, but the seller was very honest and quick responding and the item arrived by airmail a few days after I reported my concerns.

ReadyAVR-64
ReadyAVR-64

Upon getting my board in the post, the first thing I did was swap out the crystal oscillator for a turned pin socket. There are two reasons for this – firstly the pre-installed crystal was an odd speed (7.3728mhz – I prefer 16mhz), and secondly, a socket means I can change the speed as I wish. Making this change requires your usual component desoldering – I used some flux, an iron and some solderwick – once the crystal was out of the board I finished clearing the holes with a solder sucker. Break off a 3 long piece of turned pin female header and solder it in. You don’t even need to remove the middle pin as there is an unconnected hole already on the PCB.

The next thing I did was replace the pre-installed bootloader with a variant of optiboot. I can’t remember exactly where I got it, but the hex file is here. This USB bootloader uses the PE1, PE0 serial port and so I had to switch the jumpers on JP2 for it to work. Loading in the new bootloader is done through the ISP6 or ISP10 ports. I used my STK500 with AVRdude, as I’ve had some difficulties programming AVR128s with my usbasp in the past. It should be possible to follow “Arduino as ISP” instructions to reflash the board. I wont go into depth here. At some point I’ll write a guide to reflashing bootloaders onto AVRs, but there are already a lot of guides out there. For reference, I used the following two AVRdude commands to setup the bootloader and fuses on my board :

avrdude -p m128 -c STK500 -P /dev/ttyUSB0 -u -U flash:w:optiboot_atmega128.hex
avrdude -c STK500 -p m128 -P /dev/ttyUSB0 -U lfuse:w:0xff:m -U hfuse:w:0xc6:m -U efuse:w:0xff:m

At this point, if you wish to program the board using the Arduino IDE, you will need to install MegaCore. This adds extra microcontrollers, including the ATmega128 to the boards menu in the Arduino IDE. Installation is described in the “How to Install” section of the linked github page.

As I couldn’t find any documentation on the board due to the broken download link, I experimented and followed traces on the board until I worked out the following. Note that the LEDs are Active Low (setting the connected pin on the microcontroller to High turns them off).

  • LED0 = Arduino Pin 28 (PC0)
  • LED1 = Arduino Pin 29 (PC1)
  • LED2 = Arduino Pin 30 (PC2)
  • LED3 = Arduino Pin 31 (PC3)
  • BOOT = Arduino Pin 37 (PA7)

The Joystick is connected to Port B, but required the chip’s internal pullups to be enabled before it works correctly. One way this can be done in the Arduino IDE is by using digitalWrite to set the pin HIGH after having set it to be an input. Connections are as follows :

  • Joystick Up = Arduino Pin 9 (PB1)
  • Joystick Down = Arduino Pin 11 (PB3)
  • Joystick Left = Arduino Pin 10 (PB2)
  • Joystick Right = Arduino Pin 8 (PB0)
  • Joystick Click = Arduino Pin 12 (PB4)

Note that when you trigger two options at once, say for up and right, or left and click, all 5 pins trigger. The joystick connections are also Active Low, meaning the input goes low when the joystick is triggered.

The following Arduino example shows the functionality of both the LEDs and the joystick.

int LEDS[] = {28,29,30,31,37};
int Inputs[] = {8,9,10,11,12};

void setup() {
  for(int x = 0; x<5; x++){
    pinMode(LEDS[x], OUTPUT);
    digitalWrite(LEDS[x], HIGH);
  }
  for(int x = 0; x<5; x++){
    pinMode(Inputs[x], INPUT);
    digitalWrite(Inputs[x], HIGH); // enable pullup
  }

  int LED = 0;
  while(LED<5){
    pinMode(LEDS[LED%5], OUTPUT);
    digitalWrite(LEDS[LED%5], LOW);
    delay(250);
    digitalWrite(LEDS[LED%5], HIGH);
    delay(250);

    LED++;
  }
}

void loop() {
  for(int x = 0; x<5; x++){
    if(digitalRead(Inputs[x])==LOW){
      digitalWrite(LEDS[x], LOW);
    }else{
      digitalWrite(LEDS[x], HIGH);
    }
  }
}

AVRprog2 Config Settings

AVRprog2 Config Settings

As I add config files for different AVRs to my AVRprog2 setup, I intend to detail them here. Please see my other post here, for how to set AVRprog2 up on Linux and get it working with the Arduino IDE.

These files should be saved as text files in the style of (for the ATmega16) “atmega16.xml”, and placed in the folder “/usr/local/share/avrprog2/”. Super user permissions are required.

Additional Configuration Files :

The following are non-standard implementations – note they may contain errors.

ATmega32 :

<device>
	<name>ATmega 32</name>
	<signature>0x1e9502</signature>
	<flashSize>32768</flashSize>
	<flashPageSize>128</flashPageSize>
	<eepromSize>1024</eepromSize>
	<numOfFuses>2</numOfFuses>
</device>

ATmega162 :

<device>
	<name>ATmega 162</name>
	<signature>0x1e9404</signature>
	<flashSize>16384</flashSize>
	<flashPageSize>128</flashPageSize>
	<eepromSize>512</eepromSize>
	<numOfFuses>3</numOfFuses>
</device>

ATmega328P :

<device>
	<name>ATmega 32</name>
	<signature>0x1e950F</signature>
	<flashSize>32768</flashSize>
	<flashPageSize>128</flashPageSize>
	<eepromSize>1024</eepromSize>
	<numOfFuses>3</numOfFuses>
</device>

Standard Configuration Files :

ATmega16 :

<device>
	<name>ATmega 16</name>
	<signature>0x1e9403</signature>
	<flashSize>16384</flashSize>
	<flashPageSize>128</flashPageSize>
	<eepromSize>512</eepromSize>
	<numOfFuses>2</numOfFuses>
</device>

ATmega128 :

<device>
	<name>ATmega 128</name>
	<signature>0x1e9702</signature>
	<flashSize>131072</flashSize>
	<flashPageSize>256</flashPageSize>
	<eepromSize>4096</eepromSize>
	<numOfFuses>3</numOfFuses>
<!--<socket>TQFP64</socket>	use autodetection-->
</device>

ATmega1280 :

<device>
	<name>ATmega 1280</name>
	<signature>0x1e9703</signature>
	<flashSize>131072</flashSize>
	<flashPageSize>256</flashPageSize>
	<eepromSize>4096</eepromSize>
	<numOfFuses>3</numOfFuses>
<!--<socket>TQFP100</socket>	use autodetection -->
</device>

ATmega2560 :

<device>
	<name>ATmega 2560</name>
	<signature>0x1e9801</signature>
	<flashSize>262144</flashSize>
	<flashPageSize>256</flashPageSize>
	<eepromSize>4096</eepromSize>
	<numOfFuses>3</numOfFuses>
<!--<socket>auto</socket>	use autodetection -->
</device>

 

Cheap “Arduino” on a Breadboard

Cheap “Arduino” on a Breadboard – Draft

Note – This is a draft version of this post. I need to take some photos and perhaps adjust the contents. I’ve also not proofread the text yet.

TL;DR

This post got a bit excessively long as I tried to include a bit of detail around the instructions. I probably should have kept it short and to the point. To overcompensate, here is a unhelpfully concise version of the instructions :

  • Add “https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json” to the “Additional Boards Manager URLs” field in the Arduino IDE preferences (a comma is required between each URL.
  • Install MiniCore within Tools>Board>Boards Manager
  • Place Chip in development board, connect USBasp to development board, plug USBasp into computer
  • Select ATmega8, select 8MHz internal, select USBasp
  • Click Burn Bootloader
  • Load your sketch, select Sketch>Upload Using Programmer
  • Done

Introduction

Often, if you’re interested in adding a small amount of intelligence to something your building or modifying, the resources of a full blown Arduino are overkill. A great way of getting the many of the benefits of the Arduino ecosystem in a cut down package and at a lower cost is to use a standalone AVR chip similar to the one found in an Arduino Uno. The following instructions discuss using an ATmega8A chip, in the DIP 28 package, although the process is very similar for other AVR microcontroller (MCU) chips. I like the ATmega8A because while it has only 1/4 of the program memory of the ATmega328P found in most Arduino Unos and many other Arduino variants, it can be purchased for less than 60p in small (x10) quantities.

Instructions to this end are reasonably readily available on the Internet already, but I’ve recently bought some parts for my dad and so wanted to pull a guide together, specifically for the things I know he is using.

Hardware we will be using :

Only the ATmega8A is actually required, as on the assumption you have another Arduino available, you can program the chip from another Arduino in a breadboard. How to do this is covered elsewhere in detail.

Software we will be using :

MCUDude has produced a number of useful additions to the Arduino IDE which allow you to easily program a large number of stand-alone AVR MCUs. These can be found here.

The ATMega8A

<picture>

The ATmega8A uses the same core as the ATmega328, but has a reduced feature set, including fewer PWM outputs, less RAM, less EEPROM and less flash memory for programs. Here are the basic specifications :

  • Maximum speed 16MHz (with external crystal)
  • 8KB flash memory for programs
  • 1KB SRAM
  • 0.5KB EEPROM

While the chip can use an external crystal oscillator of up to 16MHz to control its speed, it (and other AVRs) also include an internal RC (Resistor Capacitor) oscillator, which can be used to run the chip at 8MHz with no external components. Using the chip in this mode allows for very streamlined operation as you can run your software on the chip and not need a single external component other than the wires providing power… although a MCU circuit with no external components or connections might not be very exciting, or much use at all. What it does mean is that you only need to add what you want.

While 8MHz is half the speed of a standard Arduino Uno, it is still amazingly fast (on an AVR it is approximately 8,000,000 processor level operations per second). More than enough for many projects.

The USBasp

<picture>

This programmer can be bought for not much money from ebay and seems to work perfectly well for almost all of my needs. The only time I’ve needed anything more comprehensive was to recover “bricked” chips, where fusebits (low level settings on the chips which define things such as operating speed or programming method) have been incorrectly set etc. Note : never throw out a chip that wont work unless you saw the magic smoke leave it – I’ve not once irreparably damaged an AVR chip no matter how hard I’ve (accidentally) tried.

If you’re feeling up to the challenge, you can even make your own, with some guidance available at this website, which I assume to be the original developer’s site. Making your own is especially relevant as they can be made using the ATmega8 we’re working with.

This programmer differs from using the USB port directly, or using an FTDI (or similar) USB to UART serial board to program an AVR MCU / Arduino in that it directly programs the chip without the need for any software to be already running on the chip. Part of the Arduino ecosystem is the use of a small program called a “bootloader”. This program runs when the chip is first powered on or reset and looks to the serial port for communications indicating that it should start reprogramming the remainder of the chip with a new program being fed in over serial. When a new chip arrives from the factory, it does not come pre-loaded with this bootloader and so another method (an in circuit programmer) is required to load in programs, or even a bootloader. Most ISPs use the SPI pins on the AVR MCU.

ATmega8, 48, 88 Development Board

<picture>

SOME ASSEMBLY REQUIRED. This board should also program the ATmega168 and ATmega328 – I’m not certain why they haven’t included these in the ebay listing. The board is nothing special, but is useful because of a number of features.

  1. The ZIF socket reduces the chance of damaging the chip or board
  2. You don’t need to count pins working out where to plug in each wire from the programmer – the programmer plugs right in
  3. The circuit includes a crystal oscillator, which makes the first programming easier
  4. It is cheap and already exists!

Setting up the Software

Install the Arduino IDE if you don’t already have it installed. This is done by going to the Arduino website software download section and following instructions for your platform. Once you have installed the Arduino IDE, check it runs by launching it. If possible, confirm it functions with a regular Arduino board by loading the “blink” example into a board. If you are unsure how to do this, the getting started part of the official website may be useful.

Once you’re up and running, navigate to the “Preferences” dialog box through the “File” menu. You will be faced with something similar to the following :

Arduino Preferences
Arduino Preferences

Note the “Additional Boards Manager URLs” edit field. In a fresh install this will be empty. Paste the URL between the following quotes (exclusive) into the field : “https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json”. If there is already something in the field, find the end and add a comma before pasting in the quoted URL. Close the Preferences dialog box by clicking the “OK” button.

Select the “Boards Manager” from the “Tools”>”Board” menu. The “Board” sub-menu may have the name of the currently selected board in its name just to make it impossible for me to be specific. There may be a flurry of activity while the software checks for updates to the available boards etc. Once it has finished, it is possible to search for specific boards. For some reason it doesn’t seem possible to search for the collection name, which would be sensible.

Boards Manager
Boards Manager

In the example image above I have searched for “atmega4” as I knew that the “atmega48” was an option in the MiniCore collection of boards. Once you find MiniCore, select it and then click “Install”. Note the “Install” button is not visible until the collection is selected. Once the install is complete, close the dialog and have a look in the “Tools”>”Boards” sub menu. You should find that a number of new options have appeared under the greyed-out heading “MiniCore”. Select the option called “ATmega8”. You’ll then notice that a number of new / different sub-menus will appear in the “Tools” menu. These can be used to exactly describe how you plan to use your ATmega8. I intend to use the chips internal 8MHz oscillator and so I have set the various options as per the following image. You should do the same!

ATmega8 Options
ATmega8 Options

So we have… ATmega8, 8 MHz internal, Disabled (default) and 2.7v. BOD stands for “Brownout Detection” – the chip will stop operating when the supply voltage drops below this value. Not something we’re specifically worried about here. I’ve never messed with LTO, but it stands for “Link Time Optimisation”.

Also note, that near the end of the “Tools” menu, there is a menu option called “Programmer” and I have selected “USBasp”. You should do the same.

Finally,  from the menu “File”>”Examples”>”Basics” select the “Blink” example to load it. Replace all occurrences of “LED_BUILTIN” with “0” (excluding quotes). For convenience, you can copy the following into a new sketch if you prefer :

/*
  Blink

  Turns 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, MEGA and ZERO
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
  the correct LED pin independent of which board is used.
  If you want to know what pin the on-board LED is connected to on your Arduino
  model, check the Technical Specs of your board at:
  https://www.arduino.cc/en/Main/Products

  modified 8 May 2014
  by Scott Fitzgerald
  modified 2 Sep 2016
  by Arturo Guadalupi
  modified 8 Sep 2016
  by Colby Newman

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Blink
*/

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

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

Click the “Verify” (tick) button in the top left of the sketch window to make sure the sketch compiles with no errors. If there are errors, double check that firstly, you’ve make the LED pin modifications correctly, haven’t accidentally introduced any errors into the code, and have correctly installed MiniCore. You may also want to check that the correct board settings were selected.

Once / if the code compiles without errors, we’re ready to move on to programming a chip.

Programming a Chip

Ensure the locking mechanism on the development board ZIF socket is unlocked / open (leaver up). Place the ATmega8A chip into the ZIF socket with pin 1 (marked by a little circular indent on the top of the chip) near the reset button (the far end from the 5×2 connector). Lock the chip in place by lowering the leaver on the socket. When soldering the ZIF socket to the board, I recommend ensuring the leaver is at the reset end of the board.

Plug the 5×2 cable connector from the programmer in – one end in the programmer, the other in the development board. Note the notch should face inwards towards the centre of the development board. If it doesn’t, you might have soldered the connector the wrong way around!

<picture>

Taking care not to short the underside of either the development board or programmer on anything metallic (a USB extension cable might help here), plug the USBasp into your computer. You shouldn’t need drivers on a Mac or Linux, but you may have to set up permissions on Linux. Check here for the (permanent version please) solution on Linux.

Bootloader and Fuses

Return to your modified “Blink” sketch. You may want to do a Save As… to keep the modifications for the future. Then, just once, the first time you program your new chip, with the USBasp and development board connected, select the menu item “Tools”>”Burn Bootloader”. This will load bootloader code into your ATmega8, but more importantly, it will set up the various fuses (low level settings) to tell the chip that you want it to operate using its internal 8MHz oscillator and any other settings recommended by the MiniCore software. The IDE should tell you that the bootloader was successfully uploaded. If it didn’t, please check that everything is connected properly and the correct options in the “Tools” menu, as detailed above, have been selected.

The Program

The final, and one of the easiest steps is to load our blink sketch into the chip. This is done by going to the “Sketch”>”Upload Using Programmer” menu item. A shortcut for this is to Shift+Click on the right facing arrow that you would use to ordinarily program an Arduino. If you notice, the “Upload” text to the right of that cluster of buttons changes to “Upload Using Programmer” when you hold the mouse over the Upload button and press the Shift key.

Upload
Upload

If you look at the development board, one of the LEDs on the board should now be flashing. This LED is connected to pin 0 on the board. If the LED is not flashing, check the computer screen to see that the program successfully uploaded.

Another advantage of programming a chip in this way is that you do not need the bootloader (when you “Upload Using Programmer” it actually overwrites the bootloader – but retains the fuse settings). This means you can use the full amount of program flash memory in the chip for your own code. While the bootloader isn’t huge, this can make the difference between your software fitting in the chip or not – especially when using one of these cheaper AVRs with less room available to begin with.

Breadboard

Now that you (should) have a program running on the chip, you can transfer the ATmega8A to a piece of breadboard. To recreate the blinking LED circuit in its minimum form, you will need :

  • One piece of breadboard long enough to hold the ATmega8A
  • Something that can provide 5v
  • Two wires for 5v and GND
  • A 1k ohm resistor
  • An LED

Wire up as follows :

Breadboard
Breadboard

Note that you don’t need the left most black wire as you can just separate the wires on the LED further to bridge back to the other black wire on IC pin 8 (8th pin counting anti-clockwise from the little black dot marking pin 1, not to be confused with Arduino digital pin 8, which is actually IC pin 14… just to confuse things!).

When working on your own projects, you will find the diagram linked here very useful. It details the features and names of various pins on the chip. Note the key item “Arduino Pin” as that is the name of the pin in the Arduino IDE.

Good luck.