my Conky configuration on Linux Mint


conky.conf in /etc/conky

use_xft yes
xftfont 123:size=8
xftalpha 0.1
update_interval 1
total_run_times 0

own_window yes
own_window_type normal
own_window_transparent yes
own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager
own_window_colour 000000
own_window_argb_visual yes
own_window_argb_value 0

double_buffer yes
draw_shades no
draw_outline no
draw_borders no
draw_graph_borders no
default_color white
default_shade_color red
default_outline_color green
alignment top_right
gap_x 0
gap_y 10
no_buffers yes
uppercase no
cpu_avg_samples 2
net_avg_samples 1
override_utf8_locale yes
use_spacer yes
minimum_size 0 0
maximum_width 130

#${color cyan}${time %a, } ${color }${time %e %B %G}
${font DejaVu Sans Mono:size=8}${execpi 60 DJS=`date +%_d`; ncal -C -h | sed s/”\(^\|[^0-9]\)$DJS”‘\b’/’\1${color cyan}'”$DJS”‘$color’/}${font}
${color cyan}${time %Z,    }${color }${time %H:%M:%S}
${color cyan}UpTime: ${color }$uptime
#${color cyan}Kern:${color }$kernel
${color cyan}CPU:${color } $cpu%         ${color red} ${acpitemp}C${color }
${cpugraph 20,130 000000 ffff00}
#${color cyan}Load: ${color }$loadavg
${color cyan}Processes: ${color }$processes
${color cyan}Running:   ${color }$running_processes

${color cyan}Highest CPU:
${color #ddaa00} ${top name 1}${top_mem cpu 1}
${color lightgrey} ${top name 2}${top cpu 2}
${color lightgrey} ${top name 3}${top cpu 3}
${color lightgrey} ${top name 4}${top cpu 4}

${color cyan}Highest MEM:
${color #ddaa00} ${top_mem name 1}${top_mem mem 1}
${color lightgrey} ${top_mem name 2}${top_mem mem 2}
${color lightgrey} ${top_mem name 3}${top_mem mem 3}
${color lightgrey} ${top_mem name 4}${top_mem mem 4}

${color cyan}MEM:  ${color } $memperc%
${membar 3,100}
${color cyan}SWAP: ${color }$swapperc%
${swapbar 3,100}

${color cyan}ROOT:    ${color }${fs_free /}/${fs_size /}
${fs_bar 3,100 /}
${color cyan}HOME:  ${color }${fs_free /home}/${fs_size /home}
${fs_bar 3,100 /home}
${color cyan}NET:
${color}Up: ${color }${upspeed wlan0} k/s
${upspeedgraph wlan0 20,130 000000 ff0000}
${color}Down: ${color }${downspeed wlan0}k/s${color}
${downspeedgraph wlan0 20,130 000000 00ffff}

#install acpi first to get Battery info: sudo apt-get install acpi
${color green}Battery:${color }
capacity:$alignr${execi 60 acpi | grep -Eo ‘[0-9]+%’}
status:$alignr${execi 60 acpi | grep -Eo ‘\w+,’ | grep -Eo ‘\w+’}
remaining:$alignr${execi 60 acpi | grep -Eo ‘(:?[0-9]+){3}’}


GPS distance measurement between two coordinates using Arduino

I knew the dimension of the LCD (Nokia 5110) as 43mm x 43mm but it looked smaller than I thought.  That’s good because I want to put it on top of the GPS (Holux M-1000).

In my previous post, I explained how to get coordinates, date & time, speed, and bearing data from GPS, Holux M-1000.  Now that I have the LCD, it’s time to add two parts to the Arduino sketch: 1) LCD driver/display, 2) distance calculation between two locations.

1. LCD Driver

First of all, I searched for a simple and small library for the LCD, Nokia 5110. There were a few different libraries for this LCD: Adafruit’s, Sparkfun’s, and Henning Karlsen’s.  Among these libraries, I chose Henning Karlsen’s because I needed only simple text display with a couple of different font sizes.  Henning Karlsen has separate library for graphics as well.  I would like to thank Henning for his sharing his nice work on the library.  Henning’s library supports 3 different font sizes: SmallFont (text and number, 6×8), MediumNumber (number only, 12×16), and BigNumber (number only, 14x 24).  Only downside of this library is that the Medium and Big fonts do not support texts but only numbers. However I would need only numbers to display with bigger fonts, this limitation was no problem with me.

2. Distance calculation between two locations

There are number of websites showing how to calculate distance between two locations from latitudes and longitudes. Movable Type Scripts shows various  calculations of distance, bearing and other useful conversions using Haversine formula and BlueMM posted the Excel formula to calculate distance which is basically the same way as Haversine.

The calculation is quite straightforward but I found there was a problem: Arduino (Atmega328p) cannot handle over 6-7th decimal digits which is very important in trigonometric calculation for short distance.

Arduino reference page says “Floats have only 6-7 decimal digits of precision. That means the total number of digits, not the number to the right of the decimal point. Unlike other platforms, where you can get more precision by using a double (e.g. up to 15 digits), on the Arduino, double is the same size as float.”

Let me give you an example.  Suppose we started from a position A (lat: 40.00, long: 80) to a position B (lat: 40.01, long: 80.00). That is, we moved 0.01 degrees in latitude only. If you calculate the distance using Haversine formula on your PC, you will get about 1,111.9m. However, Arduino calculates it as 3,110.8m. Big error!  More interesting thing is that even if you reduce the latitude difference to 0.001 or 0.0001 degrees, you get the same results, 3,110.8m. So I investigate further what exactly cause this error. Of course I know the culprit is the float precision limitation as said above. But I wanted to know which part of the calculation by Arduino cause this big error. In the Haversine formula, there are COS, SIN and ACOS functions used.  I tested a few different calculations using these functions and found the calculation of COS and SIN functions affect minimal but the problem was the ACOS.  If you calculate the formula on your PC only inside of ACOS bracket, you will get 0.9999999848. See my point? The decimal places below 6th in ACOS function is actually important to calculate the angular difference for small distance, but unfortunately Arduino cannot handle this.  Not only for small distance but for even relatively long distance (say over 1 degree for instance) there is error between the results on the PC and Arduino.

Well, so I started thinking about how to avoid trigonometric function calculation when over 6th decimal places are important. And I found a solution! Instead of calculating angular difference between two positions and THEN calculating the distance by multiplying the mean earth radius, calculating a ratio of angle between two positions (latitude and longitude separately) over 360 degrees and divide the circumference of the earth by this ratio. In other words, keep the numbers big while calculation. Arduino’s float type has a limitation on the small decimal places, but can handle relatively big numbers!

Here is my formula:

The mean circumference of the earth is 2 x 6,371,000m x π = 40,030,170m

Δd (lat) = 40,030,170 x ΔΘ (lat) / 360 (assuming ΔΘ is small)

Δd(long) = 40,030,170 x ΔΘ(long) x cosΘm / 360 (Θm: mean latitude between two positions)

Now, the distance is √[Δd (lat)^2 + Δd (long)^2]

Below is the test Arduino sketch to test my formula.  The result is 11.029m while Haversine formula for the same coordinates gives 11.119m.  This is close enough considering the accuracy of the most GPS is bigger than one meter.

float gpsLat0 = 40.0;
float gpsLat = 40.0001;
float gpsLong0 = 80.0;
float gpsLong = 80.0;

void setup()
float delLat = abs(gpsLat0-gpsLat)*111194.9;
float delLong = 111194.9*abs(gpsLong0-gpsLong)*cos(radians((gpsLat0+gpsLat)/2));
float distance = sqrt(pow(delLat,2)+pow(delLong,2));

void loop()

To be continued….

GPS (M-1000) with LCD (Nokia 5110)

Finally, I got the Nokia 5110 LCD that was ordered on eBay a few weeks ago. It took me a couple of days to find the best library for the LCD and quickly updated my Arduino program to display current location (latitude and longitude), date/time, speed, and bearing. There is 2.8V regulated power in the GPS that powers the JeonLab mini and LCD. I will upload my sketch and full detail later.

 photo GPSwithLCD5110_currentlocation.jpg

GPS (Holux M-1000) signal read using Arduino 1: coordinate/bearing/speed and UTC

Holux M-1000 is a GPS receiver with a Bluetooth.  I had used it for navigation with Palm TX and Treo700p (yes, I have long been a big fan of Palm PDA series) and Geocaching until I bought Android smartphone which has a built-in GPS module. So Holux M-1000 has been in my drawer collecting dust for more than a year. From last summer, I began to play golf and I think I’m getting better. 🙂  I searched and found a lot of Android applications for assist golfing with maps, hole/hazard information, showing how many yards left and so on. I’m a gadget mania so I downloaded most of them and tried but none of them satisfied me.  In most of cases, I didn’t bother to pull out my phone and enter my password to unlock the phone and go to the application and run and wait.  Well, one might say that why not keep the phone ON while you are playing? Yes, you can do that. But the GPS module drains battery so fast and I don’t want to miss any phone calls because of the low battery.  Not only because of the battery consumption, I can’t find any application fits me (yet). So I thought I would like to have a GPS module, very simple module, that can show distance between two locations. For example, at a tee, the first location can be marked by pressing a button on the device and from that point, the device shows how far I moved while I walk to the spot for the second shot. And then I can push another (or the same) button to clear the first point and mark current spot as the first location and do the same, and so on. What parts would I need for building this device?  Here is the list of the part I noted.

  • GPS module that can communicate with Arduino (or Jeonlab mini, of course 🙂
  • LCD: I have a 16×2 LCD but it’s bulky and shows only two lines. I have ordered popular Nokia 5110 LCD on ebay and I’m waiting for it as of this writing.
  • Arduino compatible board (preferably small)
  • Power (battery for sure)
  • some resistors, caps, wire, prototyping board, push button switches etc.

That’s when I remembered my old gadget, Holux M-1000.  It has a bluetooth which means it should have serial output somewhere between the GPS module and the bluetooth module.  I started opening up the Holux M-1000 and found RX… TX… on the PCB. YES!!  But I needed to know what voltage requirements for these pins. So I searched on internet for a datasheet or instruction manual of Holux M-1000 and found there were already some people tried to read GPS signal from the Holux M-1000 using either Arduino or PIC microcontrollers. Maybe I was not very lucky to find good articles but none of them were quite useful to give me answers what I wanted clearly.  I found the User’s Manual (1371865.pdf) from Holux homepage and I got very important information as below.

  • Pin 4 and 3 on the USB mini B connector on Holux M-1000 are TX and RX (so I don’t have to add wires from the PCB. That’s good news to make my life easier. In fact, I had thought the USB jack is only for charging the battery!)
  • Pins 5 and 1 of the USB connector are Vcharge (5V) and GND, respectively as standard USB pinouts.
  • Those two RX and TX pins’ voltage range is 3.3 – 5V
  • Data format: NMEA0183 V3.01, GGA, RMC, VTG, GSA, GSV
  • Power consumption: 40 – 50mA in normal mode, 35mA in power saving mode

Now, I’m not familiar with NMEA data format, so I searched on internet again and found some good sites here and there. There are bunch of GPS information you can get from sentences that Holux M-1000 generates periodically as GGA, RMC, VTG, GSA, and GSV, but I don’t need all of them. All I need is latitude and longitude actually, but additional information such as time and date, bearing, speed will be good to know as well.  The sentence, RMC has all of these. Well, program might be simple if I needed to read data from only one sentence, then.  photo Holux-Jeonlab.jpg The GPS (Holux M-1000) and the Jeonlab mini v1.3 with an FTDI breakout board are shown above. I have USB A to mini-B cable but I didn’t want to cut the cable, so I used a female USB-A connector as shown below. Note that only 3 pins (V+, GND, and TX from GPS) are used since I only need to read serial data from the GPS, not sending any command or data to it.  photo USBpinout.jpg And the picture below shows how they connected each other. The FTDI breakout board is connected to my computer through USB cable.  photo Holux-Jeonlabconnection.jpg While I’m testing, I need serial communication between the Jeonlab mini and my computer and I will need these pins (RX, TX on the Jeonlab mini) later when I want to modify my program.  So I decided to use the Softwareserial library which is already included in the Arduino libraries. The TX pin from the GPS is connected to the pin 10 of the Jeonlab mini.  I also connected the V+ from the GPS to the Vcc pin of the Jeonlab mini as well as GND pins. In fact, you don’t need to connect the V+ pins as long as they are powered up by their own power source, but this way I can continuously charge the GPS battery from my computer USB port. I will need more time to finish the whole program while I’m waiting for the LCD that I bought, but let me show how I have programmed so far.  It can read RMC data from the GPS and get the coordinate, bearing, speed, date and time. Thanks to ‘serial parse’ function that is included in the Arduino version >1.0, it was easy to get numeric values from the serial data coming in from the GPS. However, one tricky thing was to get the local time from UTC time and date. I had to consider time zone, DST(daylight saving time), number of days of each month, leap year, etc. That was fun to figure out how to get correct time and date. Here is my code so far. I guess it is quite straight forward, but if you have any question, please add a comment below.

 GPS distance measuring
    - GPS: Holux M-1000
    - Arduino: JeonLab mini v1.3
    - LCD: Nokia 5110
 Programmed by: Jinseok Jeon (
 Date: Sep 2013
 Revised: Oct 28, 2013

#include <SoftwareSerial.h>
SoftwareSerial gps(10, 0); // RX, TX

const int TimeZone = -5; //EST
int DSTbegin[] = { //DST 2013 - 2025 in Canada and US
  310, 309, 308, 313, 312, 311, 310, 308, 314, 313, 312, 310, 309
int DSTend[] = { //DST 2013 - 2025 in Canada and US
  1103, 1102, 1101, 1106, 1105, 1104, 1103, 1101, 1107, 1106, 1105, 1103, 1102
int DaysAMonth[] = { //number of days a month
  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
int gpsYear;
int gpsMonth;
int gpsDay;
int gpsHour;
byte gpsMin;
byte gpsSec;
//float distance;
float gpsLat0;
float gpsLong0;
float gpsLat;
float gpsLong;
float gpsSpeed; //km/h
float gpsBearing; //deg
boolean LEDstate = false;
boolean SpeedWatch50;
boolean SpeedWatch70;
boolean SpeedWatch120;

#include <LCD5110_Basic.h>

LCD5110 LCD(6, 5, 4, 2, 3); //SCLK, MOSI/DIN, DC, RST, CS/CE
extern uint8_t SmallFont[];      // 6x8 pixels
extern uint8_t MediumNumbers[];  // 12x16 pixels
//extern uint8_t BigNumbers[];     // 14x24 pixels

void setup()
  pinMode(8, OUTPUT); //LED
  digitalWrite(8, 1); //LED off
  pinMode(7, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  LCD.setContrast(70); //0-127, you need to find proper number
  LCD.print("JeonLab", RIGHT, 16);

void loop()
  int a1, a2, b1, b2;
  if (gps.available() > 1)
    if (char( == 'R' && char( == 'M' && char( == 'C')
      gps.parseFloat(); //discard unnecessary part
      a1 = gps.parseInt();
      a2 = gps.parseInt();
      b1 = gps.parseInt();
      b2 = gps.parseInt();
      gpsLatLong(a1, a2, b1, b2);
      gpsSpeed = gps.parseFloat() * 1.852; //knot to km/h
      gpsBearing = gps.parseFloat();
      if (gpsYear % 4 == 0) DaysAMonth[1] = 29; //leap year check

      //Time zone adjustment
      gpsHour += TimeZone;
      //DST adjustment
      if (gpsMonth * 100 + gpsDay >= DSTbegin[gpsYear - 13] &&
          gpsMonth * 100 + gpsDay < DSTend[gpsYear - 13]) gpsHour += 1;
      if (gpsHour < 0)
        gpsHour += 24;
        gpsDay -= 1;
        if (gpsDay < 1)
          if (gpsMonth == 1)
            gpsMonth = 12;
            gpsYear -= 1;
            gpsMonth -= 1;
          gpsDay = DaysAMonth[gpsMonth - 1];
      if (gpsHour >= 24)
        gpsHour -= 24;
        gpsDay += 1;
        if (gpsDay > DaysAMonth[gpsMonth - 1])
          gpsDay = 1;
          gpsMonth += 1;
          if (gpsMonth > 12) gpsYear += 1;
      LCD.clrRow(0);//8 pixel high row to clear (0-5)
      LCD.printNumF(gpsSpeed, 0, LEFT, 0); //km/h
      if (gpsSpeed > 2)
        LCD.printNumF(gpsBearing, 0, RIGHT, 0); //bearing in degree

      LCD.printNumI(gpsMonth, 0, 24, 2, '0');
      LCD.print("-", 12, 24);
      LCD.printNumI(gpsDay, 18, 24, 2, '0');
      LCD.print("-", 30, 24);
      LCD.printNumI(gpsYear, 36, 24);

      LCD.printNumI(gpsHour, 54, 24, 2, '0');
      LCD.print(":", 66, 24);
      LCD.printNumI(gpsMin, 72, 24, 2, '0');

      if (gpsLat0 != 0.0)
        float distLat = abs(gpsLat0 - gpsLat) * 111194.9;
        float distLong = 111194.9 * abs(gpsLong0 - gpsLong) * cos(radians((gpsLat0 + gpsLat) / 2));
        float distance = sqrt(pow(distLat, 2) + pow(distLong, 2));

        LCD.clrRow(4);//8 pixel high row to clear (0-5)
        LCD.printNumF(distance, 0, LEFT, 32);
        LCD.print("meter", RIGHT, 32);
        LCD.printNumF(distance / 0.9144, 0, LEFT, 40);
        LCD.print("yard", RIGHT, 40);
      if (gpsSpeed <= 50) SpeedWatch50 = 0;
      if (gpsSpeed <= 70) SpeedWatch70 = 0;
      if (gpsSpeed <= 120) SpeedWatch120 = 0;

      if (gpsSpeed > 50 && SpeedWatch50 == 0)
        SpeedWatch50 = 1;
        tone(11, 4978, 100);
      if (gpsSpeed > 70 && SpeedWatch70 == 0)
        SpeedWatch70 = 1;
        for (int i = 1; i <= 2; i++)
          tone(11, 4978, 100);
      if (gpsSpeed > 120 && SpeedWatch120 == 0)
        SpeedWatch120 = 1;
        for (int i = 1; i <= 3; i++)
          tone(11, 4978, 100);
  if (digitalRead(12) == LOW) //marking current position
    tone(11, 3140, 100);
    if (gpsLat0 == 0.0)
      gpsLat0 = gpsLat;
      gpsLong0 = gpsLong;
      gpsLat0 = 0.0;
      gpsLong0 = 0.0;
  if (digitalRead(7) == LOW) //LED backlight toggle
    tone(11, 2810, 100);
    digitalWrite(8, LEDstate); //LED on
    LEDstate = !LEDstate;
  if (digitalRead(9) == LOW) //for future functional button
    tone(11, 3910, 100);


void gpsTime(long UTC)
  gpsHour = int(UTC / 10000);
  gpsMin = int(UTC % 10000 / 100);
  gpsSec = UTC % 100;

void gpsLatLong(int lat1, int lat2, int long1, int long2)
  gpsLat = int(lat1 / 100) + (lat1 % 100) / 60.0 + float(lat2) / 10000.0 / 60.0;
  gpsLong = int(long1 / 100) + (long1 % 100) / 60.0 + float(long2) / 10000.0 / 60.0;

void gpsDate(long dateRead)
  gpsDay = int(dateRead / 10000);
  gpsMonth = int(dateRead % 10000 / 100);
  gpsYear = dateRead % 100; //last 2 digits, e.g. 2013-> 13

Digital Car Compass and Thermometer

My car doesn’t have a compass which I wish to have one. So I started making one using my JeonLab mini v1.3 (minimalist Arduino compatible board), popular 16×2 LCD panel with a back light LED, and a 3 axis magnetometer.  Here is the part list and pictures of the LCD, JeonLab mini v1.3 and the prototyping board.

  • LCD: 16×2 HD44780 LCD (white text on blue background)
  • JeonLab mini v1.3
  • Digital compass: MAG3110 (bought an assembled from ebay)
  • Temperature sensor: TMP36
  • Phototransistor: LTR-4206E
  • 7805 regulator
  • resistors and capacitors (see schematic diagram)
  • Car battery jack
  • prototyping board
  • push button switch
  • solid copper wire (1mm in diameter) for bracket
  • cable ties

parts photo 20130203_162415.jpg

The JeonLab mini v1.3 is so small that can be attached to the back of the LCD.

compass & LCD test photo 20121228_174420.jpg

First of all, the LCD, JeonLab mini and the magnetometer, MAG3110 have been assembled on a breadboard and tested. The magnetometer has 3 axis sensor, but because, fortunately, the most roads where I live and commute to work are relatively level. So I didn’t bother to use complicated equations, but decided to calculate simply the heading angle using ATAN from X and Y readings. And it really works just good enough. Take a look at the source Arduino code below.
JeonLab Car Digital Compass & Thermometer

LCD display
Digital compass (MAG3110)
Interior temperature
LCD backlight brightness automatic adjust

MAG3110 read: Original code from Sparkfun example code

#include #include <avr/eeprom.h>

#define MAG_ADDR 0x0E
int avgX, avgY;

struct settings_t
long maxX, minX, maxY, minY;

LiquidCrystal lcd(2,3,6,7,8,9);

void setup()
config(); //configuration of the magnetometer, MAG3110
pinMode(10,INPUT); //temperature sensor
pinMode(5,OUTPUT); //LCD backlight LED
analogWrite(5, 100);

//read previously stored calibration data from EEPROM
eeprom_read_block((void*)&settings, (void*)0, sizeof(settings));

lcd.begin(16, 2);

void loop()
//read the magnetometer and calculate heading
float heading = (atan2(readx()-avgX, ready()-avgY))*180/PI;

//read and calculate the interior temperature in celcius
float temp = (analogRead(0)/1024.0*5000.0-500)/10;

//read ambient brightness from the photo-transistor
int brightness = map(analogRead(1), 900, 1023, 50, 255);
analogWrite(5,brightness); //LCD backlight LED voltage control by PWM

//diaplay compass bearing
lcd.print(” “);
if (abs(heading) <= 22.5) lcd.print(“N “); if (abs(heading) >= 157.5) lcd.print(“S “);
if (heading >= 67.5 && heading <= 112.5) lcd.print(“E “);
if (heading <= -67.5 && heading >= -112.5) lcd.print(“W “);
if (heading > 22.5 && heading < 67.5) lcd.print(“NE”);
if (heading < -22.5 && heading > -67.5) lcd.print(“NW”);
if (heading > 112.5 && heading < 157.5) lcd.print(“SE”);
if (heading < -112.5 && heading > -157.5) lcd.print(“SW”);

if (heading < 0) heading += 360.0; //display heading lcd.setCursor(3,0); lcd.print(int(heading)); lcd.setCursor(7,0); lcd.print(int(temp)); lcd.print(“\337C”); lcd.setCursor(0,1); lcd.print(” “); lcd.setCursor(0,1); lcd.print(“Brightness: “); //show PWM value for a reference lcd.print(brightness); if (digitalRead(10) == HIGH) //monitor calibration button status { analogWrite(5,200); lcd.setCursor(0,1); lcd.print(“calibrating…..”); delay(1000); calXY(); } delay(1000); } void calXY() //magnetometer calibration: finding max and min of X, Y axis { int tempXmax, tempXmin, tempYmax, tempYmin, newX, newY; lcd.setCursor(0,1); lcd.print(“Rotate the car “); delay(1000); lcd.setCursor(0,1); lcd.print(“and press button”); delay(1000); lcd.setCursor(0,1); lcd.print(“Now, begin! “); delay(500); tempXmax = tempXmin = readx(); tempYmax = tempYmin = ready(); while(digitalRead(10) == LOW) { newX = readx(); newY = ready(); if (newX > tempXmax) tempXmax = newX;
if (newX < tempXmin) tempXmin = newX; if (newY > tempYmax) tempYmax = newY;
if (newY < tempYmin) tempYmin = newY;
settings.maxX = tempXmax;
settings.minX = tempXmin;
settings.maxY = tempYmax;
settings.minY = tempYmin;

//store new X, Y values in the EEPROM
eeprom_write_block((const void*)&settings, (void*)0, sizeof(settings));


lcd.print(“Calibration done”);
lcd.print(” “);


void config(void) //MAG3110 config taken from Sparkfun example
Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x10); // cntrl register1
Wire.write(0); // send 0x00, standby mode
Wire.endTransmission(); // stop transmitting


Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x11); // cntrl register2
Wire.write(0x80); // send 0x80, enable auto resets
Wire.endTransmission(); // stop transmitting


Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x10); // cntrl register1
Wire.write(0x19); // send 0x01, active mode
Wire.endTransmission(); // stop transmitting


void print_values(void)

int readx(void) //MAG3110 read X value taken from Sparkfun example
int xl, xh; //define the MSB and LSB

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x01); // x MSB reg
Wire.endTransmission(); // stop transmitting

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire.available()) // slave may send less than requested
xh =; // receive the byte

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x02); // x LSB reg
Wire.endTransmission(); // stop transmitting

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire.available()) // slave may send less than requested
xl =; // receive the byte

int xout = (xl|(xh << 8)); //concatenate the MSB and LSB
return abs(xout);

int ready(void) //MAG3110 read Y value taken from Sparkfun example
int yl, yh; //define the MSB and LSB

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x03); // y MSB reg
Wire.endTransmission(); // stop transmitting

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire.available()) // slave may send less than requested
yh =; // receive the byte

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x04); // y LSB reg
Wire.endTransmission(); // stop transmitting

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire.available()) // slave may send less than requested
yl =; // receive the byte

int yout = (yl|(yh << 8)); //concatenate the MSB and LSB
return abs(yout);

And the schematic diagram is below.
Schematic photo JeonLabCarDigitalCompassThermometer-1.png

I have introduced a step-by-step assembling procedure on Instructable, and here are some pictures of assembling and mounting on top of the interior mirror of my car.

assembling JeonLab mini v1.3 photo 20130203_165903.jpg

Note that there is no LED attached. A 6-pin header is attached upwards for the FTDI USB interface and 3 single header pins are attached at the bottom of the JeonLab mini to support on the prototyping board which will be attached to the back of the LCD.

JeonLab mini on the back of the LCD photo 20130209_122723.jpg

 photo 20130217_124514.jpg
The temperature sensor (TO-92 package), a voltage regulator, and a calibration switch are assembled.

finished assembly photo 20130317_163954.jpg
Next to the temperature sensor, the phototransistor (looks like a 3mm LED in black) is added to adjust the LED backlight of the LCD automatically.

wrapping heat shrink tube photo 20130409_193307.jpg
A thick solid copper wire (appx. 1mm in diameter) is used to form a simple bracket on top of the interior mirror.

finalizing bracket photo 20130409_194316.jpg
A heat shrink tube is used to insulate the copper wire bracket where it touches the LCD PCB.

attched to the mirror photo 20130409_194552.jpg
Two short cable ties are used to fix the assembled LCD and bracket on top of the mirror.

magnetometer fix photo 20130413_153144.jpg
The magnetometer is held by a small suction cup on the wind shield at the back of the mirror.

in my car photo 20130410_174041.jpg
Finally, it works!

Cheap and simple digital TV antenna

It’s been a long time since I posted the last one.  I got a new job and had to move to a new place in Windsor, Ontario and have been really busy with everything. Now I think I can resume this blogging with exciting projects.

Since I moved to this brand new house, I made a temporary TV antenna as shown below.

I found this TV antenna design from internet some time ago and it really works quite well. A matching transformer in the middle in this picture is missing since I have already removed it to a new design. This one works fine but I don’t want to put this one on top of the roof because I don’t want to take any risk of thunder or even climbing up to the roof, nor to hang it on the living room wall because it is not that small (about 1m high) and doesn’t look pretty. So I decided to test very simple antenna that is cheap, small enough to be hidden behind a picture frame, and indoor.

The aluminum foil in the kitchen is always handy. I needed a support to attach two pieces of aluminum foil and found a piece of cardboard box. The size of each side of the aluminum foil is 250mm x 215mm. I didn’t test other than this size but it works good enough. You may want to try different size and shape of similar design for your TV. I could get over 20 channels with this.


Since it is a brand new house, all the cable outlets on the walls in the living room (over the fireplace), in the master bedroom, and in the basement remain unconnected and exposed in front of the switch panel (power distribution panel) in the basement.


I wanted to put the TV in the basement and wanted to put the antenna as high as possible and hopefully to be able to hide the antenna such as behind a picture frame (I don’t have it yet though.) above the fireplace. So I tested all the cables using my multimeter and identified which one was which and connected the two cables, one from the living room and one from the basement, and connected together as shown pictures below.





Two pieces of the aluminum foil are connected to the TV antenna matching transformer and attached between the foil by using a hot glue.



A short TV cable connects the antenna matching transformer and the outlet on the wall like this.



Auto scanning of the DTV (digital TV) channels gave me 23 channels!

Now I need a picture frame to hide the antenna.