Fab Academy 2018

Programming

Overview

For embedded programming my idea was to have the tachometer running on an ATtiny44 (20 Mhz external clock) and sending this data via serial to the main ATMega328 which in turn will print to the LCD. As you can see from the electronics, I bootloaded the ATmega with an Arduino bootloader so as to be able to use libraries. As I am still beginning to learn the intricacies of embedded programming, sticking to the Arduino IDE was a simple choice.

Tachometer and Serial

Here below I include the tachometer code I wrote to program by board. I included the SoftwareSerial.h library for the Attiny to be able to use the various serial functions. Otherwise the comments are self explanatory:

//Tachometer Program

#include <SoftwareSerial.h> // include the Software serial library to run serial on Attiny45
SoftwareSerial mySerial(0, 1); // declare my serial ports 1 and 0 (TX, RX)


const byte sensorPin = A2; // set hall sensor pin PA2 = pin4 = A2
const byte buttonPin = A3;  // set buttonPin = A3
const byte ledPin1 = 8;  // Red LED pin 8
const byte ledPin2 = 7; // Green LED pin 7


byte sensordigital; // set global variable for sensing the pulse
byte prevsensordigital; // set global variable for recording the previous pulse value
volatile byte counter; // set counter variable

int rpm; // set rpm variable
unsigned long lastmillis; // set the lastmillis variable



void setup() {

  //set sensorPin (A2) as INPUT
  pinMode(sensorPin, INPUT);
  pinMode(buttonPin, INPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);

  counter = 0;
  sensordigital = 0;
  prevsensordigital = 0;
  rpm = 0;
  lastmillis = 0;

  //Set the baud rate 9600 bits per second
  mySerial.begin(9600);

}

void loop() {

  // analogRead (ADC) sensorPin to provide int = SensorValue
  int sensorValue = analogRead(sensorPin);
  int  Maxthresh = 515; // max threshold analogue reading
  int Minthresh = 510; // min threshold analogue reading
  prevsensordigital = sensordigital; // saving the pervious sensor value and printing the current one

  // button print sensorValue
  if (digitalRead(buttonPin) == 0) {
    mySerial.println(sensorValue);
    digitalWrite(ledPin1, HIGH);
    }
    else {
    digitalWrite(ledPin1, LOW);
    }


  if (sensorValue >= Maxthresh || sensorValue <= Minthresh) {
    // mySerial.write("1");
    digitalWrite(ledPin2, HIGH);
    sensordigital = 1;
  }     else {
    // mySerial.write("0");
    digitalWrite(ledPin2, LOW);
    sensordigital = 0;
  }

  if (prevsensordigital == 1 && sensordigital == 0) {
    counter ++;
    }

   if (millis() - lastmillis >= 1000) {
   rpm = counter * 60;
   mySerial.print("RPM="); //print the word "RPM" and tab.
   mySerial.print(rpm); // print the rpm value.
   mySerial.print(" Hz="); //print the word "Hertz" and tab.
   mySerial.print(counter); // print the rpm value.
   lastmillis = millis();
   counter = 0;
   }

   delay(5);   // Wait 10 milliseconds

}


LCD and I2C

So I was able to directly read the tachometer using the serial monitor window, and used this mostly while testing my generator. However, to read and display the readings on an LCD I was going to use my nikoduino (ATmega328) which I bootloaded to function just like an Arduino for simplicity sake.

Also the idea here was to use various pins to connect a LED array to test how the turbine/generator fares under different loads. But this will have to be in the subsequent spiral development.

The code for reading serial and communicating with the LCD is relatively simple, here is a good tutorial. Again I relied on libraries for simplicities sake, mainly the LiquidCrystal_I2C.h. The rest is self explanatory.

Using I2C Adapter

LCD display modules usually require a lot of connections. Even in 4-wire mode there are still a total of seven connections made to the Arduino digital I/O pins. As an Arduino Uno has only 14 digital I/O pins that’s half of them used up for the display.

The adapter only uses four connections, two of them are for power:

In I2C communications there is the concept of Master and Slave devices. There can be multiples of each but there can only be one Master at any given moment. In most Arduino applications one Arduino is designated Master permanently while the other Arduinos and peripherals are the Slaves.

The Master transmits the clock signal which determines how fast the data on the bus is transferred. There are several clock speeds used with the I2C bus. The original design used 100 KHz and 400 KHz clocks. Faster rates of 3.4 MHz and higher are available on some I2C configurations.

For most Arduino designs a 400 KHz clock frequency is used. Every device on the I2C bus has a unique address. When the Master wants to communicate with a Slave device it calls the Slaves address to initiate communications.

In our simple design we will be using our Arduino as a Master and the I2C adapter for the LCD display as the Slave. The A4 pin is used as the SDA connection while A5 is used as the SCL connection.

//Program for reading tachometer and outputting to LCD

// Include Wire Library for I2C
#include <Wire.h>
// Include NewLiquidCrystal Library for I2C
#include <LiquidCrystal_I2C.h>

// Define LCD pinout
const int  en = 2, rw = 1, rs = 0, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 3;

// Define I2C Address
const int i2c_addr = 0x27;
int incomingByte = 0;


LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);

// select the input pin for the Hall sensor

void setup() {
  lcd.begin(16,2);
  //Set the baud rate 9600 bits per second
  Serial.begin(9600);
  lcd.setCursor (0,0);
}

void loop() {

  // when characters arrive over the serial port...
  if (Serial.available()) {
    // wait a bit for the entire message to arrive
    delay(100);
    // clear the screen
    lcd.clear();
    // read all the available characters
    while (Serial.available() > 0) {
      // display each character to the LCD
      lcd.write(Serial.read());
    }
  }
}