…how I Learned to Stop Worrying and Love I2C

Some form of display is often vital on your arduino projects.Let me introduce you to the HD44780 character LCD.

It’s quite a common and cheap display solution that is relatively easy to use. It often finds its way into many arduino starter kits for these reasons. Ive used it a few times in my projects but have always been annoyed by one aspect…. the high amount of pins and the requirement of a resistor for the backlight and a potentiometer for the contrast.

The typical wiring setup for the display

As you can see the board uses up 6 data pins on your board which can be a pain on the smaller boards I’ve been using lately. Then I discovered I2C (I squared C).

I2C is a method of using addresses to run many devices on only 2 data lines.

With this we can run these LCD displays with a total of 4 wires. This is handy on boards like the ESP8266 or ESP32 with few pins. I plan on using a I2C compatible display on a project in the near future. I ordered the larger 4 line version in fact.

The code for the I2C display is quite similar to the regular versions.

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 columns and 2 row display

void setup() {
  lcd.init();       //initialize lcd screen
  lcd.backlight();  // turn on the backlight
}

void loop() {
  delay(1000);                   //wait for a second
  lcd.setCursor(0,0);            // tell the screen to write on the top row
  lcd.print("LCD TEST");         // tell the screen to write “hello, from” on the top row
  lcd.setCursor(0,1);            // tell the screen to write on the bottom row
  lcd.print("Hello World!");     // tell the screen to write "Hello World!" on the bottom row
}

Objects in Space Panel Meter Tutorial

I have cleaned up my code from my previous post and want to make it available for anyone to try out themselves.
This code drives two 5v volt meters much like the developers have in their MkII console.

Remember to set “hardware=true” in your game’s config file or else it wont work!

Running the code below!
/* Objects in Space Panel Meters
   This example displays telemetry from the game on an LCD and 5v panel meters. 
   It uses the built-in LiquidCrystal library - see
   https://www.arduino.cc/en/Reference/LiquidCrystal for details.

   DISPLAYS POWER FLOW AND TOTAL POWER AS A PWM ON THE LCD SCREEN AND
   PASSES IT TO PWM PINS 9 AND 10 FOR USE ON 5V PANEL METERS.

   The LCD is only used to display data for debuging purposes and can be
   omitted without affecting the meters.
   
   CODE BY DAK47922 - http://www.wolfpack.xyz/blog
   ----------------
*/
#include <LiquidCrystal.h>
#include <ArduinosInSpace.h>
int flow; //Declare our variables as integers
int power;

// Initialise the LiquidCrystal library
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// Create an ObjectsInSpace object. The first parameter is the
// serial interface to use. The second is the number of values
// we're requesting from the game.
ObjectsInSpace OIS(Serial, 2);

void setup() 
{
  pinMode(9, OUTPUT); // POWER FLOW PWM TO METER
  pinMode(10, OUTPUT); // BATTERY PWM TO METER
  
  // set up the LCD's number of columns and rows:
  // specific for a 16x2 LCD screen (change this for different sizes)
  lcd.begin(16, 2);

  Serial.begin(9600); //must be 9600
  OIS.begin(); //begin the handshake/synchronisation with the game

  // register the command to get the power flow from the game.  (a value between -100 and 100)
  OIS.registerInt(POWER_FLOW_PERCENT, powerflowCallback);
  // register the command to get the total power from the game. (a value between 0 and 100)
  OIS.registerInt(POWER_LEVEL_PERCENT, powerlevelCallback);

  OIS.activate(); //stop syncing and ACTIVATE
}

void loop() 
{
  OIS.update(); //required to keep getting info from the game.
}

// because we registered this in setup(), this gets called every time
// OIS.update() is called. therefore our info is refreshed
void powerflowCallback(int channel, int data)
{
  flow = map(data, -100, 100, 0, 255);    // Converts our -100 to 100 value to a useable PWM value (0 to 255)
  lcd.setCursor(0,0);                     // Set the cursor to the top left of the screen (0,0)
  lcd.print("FLOW PWM:   ");              // Prints our label on the screen plus 3 empty spaces to insure our value which can be 1, 2, or 3 digits is properly cleared and reprinted
  lcd.setCursor(9,0);                     // Backs up 3 spaces to print our data value on the empty spaces from the previous line
  lcd.print(flow);                        // prints our PWM value
  analogWrite(9, flow);                   // Writes our PWM value to pin 9
}


void powerlevelCallback(int channel, int data)
{
  power = map(data, 0, 100, 0, 255);      // Converts our 0 to 100 value to a useable PWM value (0 to 255)
  lcd.setCursor(0, 1);                   //set the cursor to the 1st position of the second row
  lcd.print("BATT PWM:   ");             // Prints our label plus 3 empty spaces like above
  lcd.setCursor(9,1);                    // Backs up 3 spaces to print our data value on the empty spaces from the previous line
  lcd.print(power);                      // prints our PWM value
  analogWrite(10, power);                // Writes our PWM value to pin 10
}