Sunday 28 July 2013

Texas Instruments TM4C123G LaunchPad

Finally received my USD12 TM4C123G evaluation kit last week after one month. I think this evaluation kit replace the Stellaris LM4F120. This low cost starter kit really pack a lot of punch with 32bit Arm Cortex M4 CPU and 256Kb program memory and 32kb SRAM running at 80MHz. The peripheral on this CPU is massive if compared to the ATMEGA328 used in the Arduino Uno. Both board have about the same size. Below is a comparison table between Tiva C series and Arduino Uno:


Arduino Uno Tiva C Launchpad
CPU Atmel ATMEGA328 8-bit TM4C123G 32-bit (2x)
Price USD29 USD12
Flash memory 32Kb 256Kb
RAM 2Kb 32Kb
EEPROM 1Kb 2Kb
Clock (max) 20Mhz 80Mhz
IO voltage 5V 3.3V (5V input tolerant)
Digital IO 14 43
Analog input 6 10-bit 2 1-MSP 12 bit
SPI 1 4
Serial port UART 1 8
Ext int 2 43 (71 int)
PWM 6 16
I2C yes yes (6)
USB 2.0  OTG no yes
Quadrature encoder no yes
CAN bus no yes
Analog comparator no yes
Temperature sensor no yes
Watchdog timer no yes
RTC no yes
DMA no yes
User LED 1 1 (3 colors)
User button 0 2


Getting started on this board is very easy with Arduino like IDE called Energia. This board is not yet displayed under the supported hardware, but it work just fine with the LM4F120 selected.



Below is the board connected to the Nokia LCD5110 running sample program from
http://forum.stellarisiti.com/forum/64-energia-libraries/ :


The available library is still not as much as Arduino, but I hope it will continue to be ported. I wish to see the Arduino's TVout library being ported to this board, as with the 32K RAM and a lot of horsepower, much higher resolution can be achieved.



 

Friday 26 July 2013

Xedos 6 front lower arm bushing replacement

I noticed my Mazda Xedos 6 lurched to the left when I accelerate. Suspected my right lower arm's bushing. Below video clips (in slow motion) confirmed it.







Went looking for the parts at nearby autoparts shop. I requested for bushings for Mazda 626 V6 (1994 model) which is also known as Cronos (chasis GE), since the xedos 6 share many suspension parts and engine with this model. To my suprise, they gave me this Kia/Hyundai part. On the right is the original part from my car.


Quick check on the web, this part belong to Kia Credos, but not sure what it is called in Malaysia.
Also get this rubber bushing part as well on the right. Both the rear and the front bushing cost me RM140 and RM48 respectively.




The front busing need to be pressed in at an engineering shop for RM8.
 If you never heard or seen Xedos 6, below is the car.



Friday 19 July 2013

Quadcopter with miniHD cam

This is a little quadcopter that I bought for RM100 sometime back. I attached a small HD camera bought at ebay for USD30. This make nice little spydrone.

Below is the inside of the little HD camera.


Below is the link to youtube video taken with the contraption until it got stuck on tree...

https://www.youtube.com/watch?v=MhUAeI0GTEI


Arduino Muslim prayer time and analog clock using TV

Salam.
Utilizing the Arduino TVout library, I implemented analog clock with RTC DS1307 I2C together with muslim pray time calculation. The TV picture is as below:






Uses arduino uno board connected to reverse camera TV for display, and tinyRTC for the timekeeper.
With this code and RM40 parts, we can turn all that old TV into salat time display for masjid, surau or your own house. Below is how it look like on my 40 inch LCD tv.


How it look like in PIP window:



Below is the code for this project with embedded setting for Kuala Lumpur, Malaysia. Currently not able to change via button or serial port due to memory limitation.To change clock, date, pray time calculation parameters, they need to be changed in the code accordingly.  Please refer to the comments in the code. Will enhance it again later  for user friendliness. Pray time accuracy need to be worked on further too.

// Muslim prayer time on TV by Omar Badar, July 19, 2013
// Uses the fantastic TVout library http://code.google.com/p/arduino-tvout/
// TVout RTC is code snippet from http://giantmetalrobot.blogspot.com/2011/05/arduino-analog-clock.html
// Prayer time calculation is from http://3adly.blogspot.com/2010/07/prayer-times-calculations-pure-c-code.html

#include <TVout.h>
#include "Wire.h"
//#include <pollserial.h>
#include <fontALL.h>

TVout TV;
//pollserial pserial;
const int buttonPin = 3;
#define DS1307_I2C_ADDRESS 0x68  // This is the I2C address
// Global Variables
long previousMillis = 0;        // will store last time time was updated
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
long interval = 200;
int tvx,tvy,tvradius,x2,y2,x3,y3;
int zero=0;
char  *Day[] = {"","Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
double fajr, sunRise, zuhr, asr, maghrib, isha;


// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}

// Gets the date and time from the ds1307 and prints result
void getDateDs1307()
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
//Wire.write(0x00);
Wire.write(zero);
Wire.endTransmission();

Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

// A few of these need masks because certain bits are control bits
second     = bcdToDec(Wire.read() & 0x7f);
minute     = bcdToDec(Wire.read());
hour       = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
dayOfWeek  = bcdToDec(Wire.read());
dayOfMonth = bcdToDec(Wire.read());
month      = bcdToDec(Wire.read());
year       = bcdToDec(Wire.read());

}

void setDateDs1307()
{
 
   // Below changes will happen when pin 3 is pull high. Short pin 3 to ground once changes to clock is done.
   // Run out of RAM for serialport or button date, lon, lat adjust. will work on it later.
   minute=38;
   hour=22;
   dayOfWeek=5;
   dayOfMonth=18;
   month=7;
    /*
   second = (byte) ((pserial.read() - 48) * 10 + (pserial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.
   minute = (byte) ((pserial.read() - 48) *10 +  (pserial.read() - 48));
   hour  = (byte) ((pserial.read() - 48) *10 +  (pserial.read() - 48));
   dayOfWeek = (byte) (pserial.read() - 48);
   dayOfMonth = (byte) ((pserial.read() - 48) *10 +  (pserial.read() - 48));
   month = (byte) ((pserial.read() - 48) *10 +  (pserial.read() - 48));
   year= (byte) ((pserial.read() - 48) *10 +  (pserial.read() - 48)); */
  
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.write(zero);
   Wire.write(decToBcd(second));    // 0 to bit 7 starts the clock
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));      // for 12 hour am/pm, need to set bit 6 (also need to change readDateDs1307)
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
}


void printTime()
{
int hours, minutes;
char s[12];
TV.set_cursor(0,0);
TV.print( char( hour/10 + 0x30) );
TV.print( char( hour%10 + 0x30) );
TV.print(":");
TV.print( char(minute/10 + 0x30));
TV.print( char(minute%10 + 0x30));
TV.print(":");
TV.print(char (second/10+0x30));
TV.print(char (second%10+0x30));


TV.set_cursor(8,9);
TV.print(char(dayOfMonth/10+0x30));
TV.print(char(dayOfMonth%10+0x30));
TV.print("/");
TV.print(char(month/10+0x30));
TV.print(char(month%10+0x30));
TV.set_cursor(10,18);
TV.print("20");
TV.print(char(year/10+0x30));
TV.print(char(year%10+0x30));
TV.set_cursor(10,26);
TV.print(Day[dayOfWeek]);

TV.print(40,0,"< KL Waktu Sembahyang >");
doubleToHrMin(fajr, hours, minutes);
sprintf(s,"Suboh %d:%d",hours,minutes);
TV.print(93,8,s);
doubleToHrMin(zuhr, hours, minutes);
if(hours==12)
sprintf(s,"Zohr %d:%d",hours,minutes);
else sprintf(s,"Zohr %d:%d",hours-12,minutes);
//if(hours==13)sprintf(s,"Z=%d:%d",hours-12,minutes);
TV.print(96,18,s);
doubleToHrMin(asr, hours, minutes);
sprintf(s,"Asr %d:%d",hours-12,minutes);
TV.print(100,28,s);
doubleToHrMin(maghrib, hours, minutes);
sprintf(s,"Mgb %d:%d",hours-12,minutes);
TV.print(100,38,s);
doubleToHrMin(isha, hours, minutes);
sprintf(s,"Isy %d:%d",hours-12,minutes);
TV.print(100,48,s);
//TV.print(10,70,"Kuala Lumpur");

TV.draw_circle(tvx,tvy,tvradius-5,BLACK,BLACK);

float angle = second*6 ;
angle=(angle/57.29577951) ; //Convert degrees to radians 
x3=(tvx+(sin(angle)*(tvradius-6)));
y3=(tvy-(cos(angle)*(tvradius-6)));
TV.draw_line(tvx,tvy,x3,y3,WHITE);
angle = minute * 6 ;
angle=(angle/57.29577951) ; //Convert degrees to radians 
x3=(tvx+(sin(angle)*(tvradius-11)));
y3=(tvy-(cos(angle)*(tvradius-11)));
TV.draw_line(tvx,tvy,x3,y3,WHITE);
angle = hour * 30 + int((minute / 12) * 6 )   ;
angle=(angle/57.29577951) ; //Convert degrees to radians 
x3=(tvx+(sin(angle)*(tvradius-20)));
y3=(tvy-(cos(angle)*(tvradius-20)));
TV.draw_line(tvx,tvy,x3,y3,WHITE);
}


void setup()  {
pinMode(buttonPin, INPUT);
Wire.begin();
getDateDs1307() ;
//TV.begin(_NTSC,184,72);
//the circle didn't look very round with 184,72
TV.begin(_NTSC,140,85);
TV.select_font(font4x6);
TV.clear_screen();
//TV.println("TV Clock");
tvx= TV.hres()/2;
tvy=TV.vres()/2;
tvradius=TV.vres()/3 ;
//clock face
 TV.draw_circle(tvx,tvy,tvradius,WHITE);
//hour ticks
for( int z=0; z < 360;z= z + 30 ){
  //Begin at 0° and stop at 360°
  float angle = z ;
  angle=(angle/57.29577951) ; //Convert degrees to radians
  x2=(tvx+(sin(angle)*tvradius));
  y2=(tvy-(cos(angle)*tvradius));
  x3=(tvx+(sin(angle)*(tvradius-5)));
  y3=(tvy-(cos(angle)*(tvradius-5)));

  TV.draw_line(x2,y2,x3,y3,WHITE);
}
//TV.set_hbi_hook(pserial.begin(57600));
if(digitalRead(buttonPin)==HIGH) setDateDs1307();
//calcPrayerTimes(2013,7,19,101.7,3.2,8,19.5,17.5,fajr, sunRise, zuhr, asr, maghrib, isha);
}


void loop() {
// if (pserial.available()) {
//   TV.print((char)pserial.read());
//  }

// other processing here maybe 
calcPrayerTimes(year, month, dayOfMonth, 101.7, 3.2, 8, -19.5, -19, fajr, sunRise, zuhr, asr, maghrib, isha);

unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval) {
  // save the last time you printed and updated

  previousMillis = currentMillis;
  TV.delay(1);
  printTime();
  //read RTC
  getDateDs1307() ;
}

}

/*-------------------------------------------------------------------------------------*/
// PRAYER TIME (by Mahmoud Adly Ezzat, Cairo)

//convert Degree to Radian
double degToRad(double degree)
{
    return ((3.1415926 / 180) * degree);
}

//convert Radian to Degree
double radToDeg(double radian)
{
    return (radian * (180/3.1415926));
}

//make sure a value is between 0 and 360
double moreLess360(double value)
{
    while(value > 360 || value < 0)
    {
        if(value > 360)
            value -= 360;

        else if (value <0)
            value += 360;
    }

    return value;
}

//make sure a value is between 0 and 24
double moreLess24(double value)
{
    while(value > 24 || value < 0)
    {
        if(value > 24)
            value -= 24;

        else if (value <0)
            value += 24;
    }

    return value;
}

//convert the double number to Hours and Minutes
void doubleToHrMin(double number, int &hours, int &minutes)
{
    hours = floor(moreLess24(number));
    minutes = floor(moreLess24(number - hours) * 60);
}

void calcPrayerTimes(int year, int month, int day,
                     double longitude, double latitude, int timeZone,
                     double fajrTwilight, double ishaTwilight,
                     double &fajrTime, double &sunRiseTime, double &zuhrTime,
                     double &asrTime, double &maghribTime, double &ishaTime)
{
    double D = (367 * year) - ((year + (int)((month + 9) / 12)) * 7 / 4) + (((int)(275 * month / 9)) + day - 730531.5);

    double L = 280.461 + 0.9856474 * D;
    L = moreLess360(L);

    double M = 357.528 + (0.9856003) * D;
    M = moreLess360(M);

    double Lambda = L + 1.915 * sin(degToRad(M)) + 0.02 * sin(degToRad(2 * M));
    Lambda = moreLess360(Lambda);

    double Obliquity = 23.439 - 0.0000004 * D;
    double Alpha = radToDeg(atan((cos(degToRad(Obliquity)) * tan(degToRad(Lambda)))));
    Alpha = moreLess360(Alpha);

    Alpha = Alpha - (360 * (int)(Alpha / 360));
    Alpha = Alpha + 90 * (floor(Lambda / 90) - floor(Alpha / 90));

    double ST = 100.46 + 0.985647352 * D;
    double Dec = radToDeg(asin(sin(degToRad(Obliquity)) * sin(degToRad(Lambda))));
    double Durinal_Arc = radToDeg(acos((sin(degToRad(-0.8333)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));

    double Noon = Alpha - ST;
    Noon = moreLess360(Noon);


    double UT_Noon = Noon - longitude;


    ////////////////////////////////////////////
    // Calculating Prayer Times Arcs & Times //
    //////////////////////////////////////////

    // 2) Zuhr Time [Local noon]
    zuhrTime = UT_Noon / 15 + timeZone;

    // Asr Hanafi
    //double Asr_Alt =radToDeg(atan(2+tan(degToRad(latitude - Dec))));
    double Asr_Alt =radToDeg(atan(1.7+tan(degToRad(latitude - Dec))));
    // Asr Shafii
    //double Asr_Alt = radToDeg(atan(1 + tan(degToRad(latitude - Dec))));
    double Asr_Arc = radToDeg(acos((sin(degToRad(90 - Asr_Alt)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));
    Asr_Arc = Asr_Arc / 15;
    // 3) Asr Time
    asrTime = zuhrTime + Asr_Arc;

    // 1) Shorouq Time
    sunRiseTime = zuhrTime - (Durinal_Arc / 15);

    // 4) Maghrib Time
    maghribTime = zuhrTime + (Durinal_Arc / 15);


    double Esha_Arc = radToDeg(acos((sin(degToRad(ishaTwilight)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));
    // 5) Isha Time
    ishaTime = zuhrTime + (Esha_Arc / 15);

    // 0) Fajr Time
    double Fajr_Arc = radToDeg(acos((sin(degToRad(fajrTwilight)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));
    fajrTime = zuhrTime - (Fajr_Arc / 15);

    return;
}

//end sketch