Tuesday 5 November 2013

BeagleBone Black (BBB) and Ubuntu + Python + openCV + BBIO + WiFi

BeagleBone Black (BBB)



My latest "embedded controller" toy is a BeagleBone Black or BBB. I have been playing with it for quite a while now since it was purchased in Aug 2013. The BBB came with preinstalled Linux Angstrom. One thing about Angstrom is it is very fast boot up time, and have simple LAN over USB. To get started, we just need to connect the USB mini cable to a PC, and there you go. It also have a preinstalled "Bonescript", "Cloud9", and BoneCV (small version of OpenCV).

To get started with the BoneCV on BBB, I followed the excellent tutorial by Derek Molloy (link below)

http://derekmolloy.ie/beaglebone/beaglebone-video-capture-and-image-processing-on-embedded-linux-using-opencv/

His tutorial show how to connect to a USB camera, and compile C code to perform some basic image capture and processing from the terminal. This is only text based samples, and to view the captured or processed image, you have to use other apps to open it.

I have also installed VNC server on the Angstrom so I could remote connect and eliminate the HDMI screen, as well as Python.


Since I am not able to run the standard EDGE user interface for Python, I have an SD card installed with Ubuntu image, which was downloaded from below link:

http://www.armhf.com/index.php/boards/neaglebone-black/#wheezy

To install openCV in Ubuntu, resize the SD card and refer to installopencv.sh from desktop.
To install Python Edge, run "sudo -apt -get -y install idle".


Since then, I have also installed Adafruit BBIO library as well as WiFI library. Currently I am able to execute  Python Demo programs, such as "Mosse.py", which is pattern matching image processing sample.



To get this to work with the image size that I want, I slightly modified the "video.py" to have this additional codes (in yellow):

 def create_capture(source = 0, fallback = presets['chess']):
    '''source: <int> or '<int>|<filename>|synth [:<param_name>=<value> [:...]]'
    '''
    source = str(source).strip()
    chunks = source.split(':')
    # hanlde drive letter ('c:', ...)
    if len(chunks) > 1 and len(chunks[0]) == 1 and chunks[0].isalpha():
        chunks[1] = chunks[0] + ':' + chunks[1]
        del chunks[0]

    source = chunks[0]
    try: source = int(source)
    except ValueError: pass
    params = dict( s.split('=') for s in chunks[1:] )

    cap = None

    if source == 'synth':
        Class = classes.get(params.get('class', None), VideoSynthBase)
        try: cap = Class(**params)
        except: pass
    else:
        cap = cv2.VideoCapture(source)
        if 'size' in params:
  
            w, h = map(int, params['size'].split('x'))
            cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, w)
            cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, h)
    if cap is None or not cap.isOpened():
        print 'Warning: unable to open video source: ', source
        if fallback is not None:
            return create_capture(fallback, None)

    cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 320)
    cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 240)   

    return cap



 WiFi Installation
-----------------


To get the WiFi to work, I basically followed the instruction from this page:

http://dotnetdavid.wordpress.com/2013/09/14/beaglebone-black-set-up-wireless-on-ubuntu/

To replace the original file, we need to be in root access. We can either "sudo", or just login as root. To login as root in Ubuntu, run sudo passwd root, and change root password.

To confirm that the WiFi is up and running, run "ifconfig" and ensure that the wlan0 has IP address assigned as below:



 BBIO library
--------------


To install BBIO library, just follow the instruction from this webpage:

http://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/installation

Using this library, I can connect an LED to one of the IO pin and blink it.
One thing to note is the library will only work if you login as root, or execute Python with sudo command.

To be continue...


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



Saturday 11 May 2013

Inside cheap OBD2 ELM327 scantool





Inside cheap OBD2 ELM327 interface bought from china through Ebay (2 different model). 

Inside Android tablet Q88

Inside a cheap china A13 Android 4.1.1 tablet (Q88). Tablet bought at RM179 in Low Yat.






MX5 high low absorber spring swap

My 1992 MX5 ride is not very comfortable  I have Cusco hi-low absorber on my car. I notice that the spring for the rear assembly is shorter, thus the harsher ride. So what I did is to take the from Cusco spring and put it at the back. Picture below (right to left) show MX5 OEM rear absorber/spring, rear cusco/front cusco spring, rear cusco absorber and original cusco rear spring, front cusco absorber and cusco front spring.
The result is: much improved and comfortable ride. What about the front? I put back the OEM spring and absorber for now until I found replacement cusco spring..


Arduino chart recorder using reverse camera TV

Arduino rock!
Created a simple program to monitor oven temperature using arduino, TCmux shield, and TV out library.
Take note that the picture attached do not have the TCmux circuit connected.


Code as below:


// Note:        This code uses TV-OUT for Arduino library. Also credit to Shadi Soundation for the TV oscilloscope code

#include <TVout.h>
#include <fontALL.h>
TVout TV;
#include <SPI.h>

#define CS_TEMP  8 // MAX6674/6675 /CS Line
//#define MUX_EN   7 // ADG608 MUX Enable
#define MUX_A0   4 // ADG608 Addr0
#define MUX_A1   5 // ADG608 Arrd1
#define MUX_A2   6 // ADG608 Addr2
#define BUZZER   3 // BUZZER pinout3
#define SO 12    // MISO
#define RESETBTN  2// MISO
#define SCK 13   // Serial Clock


int temperature = 0;

int channelAI = A0;      // select the input pin for the Oscilioscope
int scaleYAI = A1;       // select the input pin for the Y (horizontal) potentiometer
int scaleXAI = A2;       // select the input pin for the X (Vertical) potentiometer

int delayVariable = 0;   // define a variable for the Y scale / delay
int xVariable = 0;       // define a variable for the x scale 
int yCtr = 0;            // define a variable for the y counter used to collect y position into array
int posy = 0;            // define a variable for the y position of the dot 
int myArray[127];         // define an array to hold the data coming in 
int RESETval = 0;

unsigned long cure_t=0;
unsigned long base_t=0;
unsigned long minute=0;
unsigned long seconds;

void setup()  {
  
TV.begin(_PAL,128,96); //for devices with only 1k sram(m168) use TV.begin(_PAL,128,56)



 pinMode(SO, INPUT);
  pinMode(SCK, OUTPUT);
  pinMode(CS_TEMP, OUTPUT);
  pinMode(MUX_A0, OUTPUT);
  pinMode(MUX_A1, OUTPUT);
  pinMode(MUX_A2, OUTPUT);
  //pinMode(MUX_EN, OUTPUT);
  pinMode (BUZZER, OUTPUT);
  pinMode (RESETBTN, INPUT);

  digitalWrite(CS_TEMP,HIGH);// Set MAX7765 /CS High
  //digitalWrite(MUX_EN,HIGH); // Enable on
  digitalWrite(BUZZER,LOW); // Enable on

  digitalWrite(MUX_A0,LOW);
  digitalWrite(MUX_A1,LOW);
  digitalWrite(MUX_A2,LOW);
  //Serial.begin(9600);
  TV.select_font(font6x8);
  TV.println(15,30,"TIM TEMPERATURE"); 
  TV.println(15,50," OVEN CHECKER"); 
  draw_axis();
  delay(5000);
  TV.clear_screen();
  draw_axis();
}

void loop()
{
  //base_time==millis();
  //cure_time==0;
  update_display();



void update_display() {
exit_loop:  
  //base_t==Read_time();
  //delayVariable = analogRead(scaleYAI);
  //delayVariable = (5000/100);
  delayVariable = 100; // change to plot slower or faster
  //xVariable = analogRead(scaleXAI);
  xVariable = 1;  // 
  TV.select_font(font4x6);
  for(yCtr = 0; yCtr < 127; yCtr += 1)   // the for loop runs from 0 and < 127, it fills the array with 126 records
    {     
      //if(!(millis() / 1000)) seconds++;

      seconds=millis()/1000;
      minute=seconds/60;
      // check door status
       if(digitalRead(RESETBTN)) 
       {
         TV.clear_screen();
         base_t=seconds;

         TV.println(90,10,seconds);
         TV.println(90,18,"OPEN ");
         cure_t=0;
         draw_axis();
         goto exit_loop;
       }
       else
       {
         TV.println(90,18,"CLOSE");
         cure_t=millis()/1000 - base_t;      
         TV.println(90,2,cure_t/60);
         TV.println(90,10,seconds);
       }      
       
      //posy = analogRead(channelAI);       // read the value from the sensor:
      temperature = Read_Temperature();   // + temptol;    
      posy = 120-temperature;     
      //-------------------------------------------------------------------------------------------------
      //check temp here
      //
      if((cure_t > 60*30) || (cure_t < 60*60))   // check low temp during ramp
       {
        if(temperature < 100) error_low();   
       } 
    
      if((cure_t > 60*60) || (cure_t < 60*60*2))  // check low temp during soak first hour
       {
        if(temperature < 175) error_low();   
       } 
      
      if((cure_t > 60*60*2) || (cure_t < 60*60*4))  // check low temp during soak 2, 3, 4  hour
       {
        if(temperature < 175) error_low();   
       }    
      
       if((cure_t > 60*60*4) || (cure_t < 60*60*5))  // check high temp during cool down
       {
        if(temperature > 175) error_high();   
       }       
      
       if(temperature > 185) error_high();   // check high temp at any time

      
      
      //-------------------------------------------------------------------------------------------------

      TV.select_font(font4x6);
      TV.println(30,2,temperature);
      TV.println(50,2,"*C, Cure=       m");

      myArray[yCtr] = (posy/xVariable);   // scale the value based on the x scale potentiometer 
      delay (delayVariable);           // scale the y collection of data using the delay from the y potentiometer  

       TV.set_pixel(yCtr, myArray[yCtr], 1); // Prepare the 126 pixels      
    }
  
    yCtr == 0;                 
      TV.clear_screen();
      draw_axis();
  for(yCtr = 0; yCtr < 127 ; yCtr += 1)  // for loop runs 126 times
    {
       TV.get_pixel(yCtr, myArray[yCtr]); // Output to TV
    }

       yCtr == 0;                         


void error_low()
{
  TV.select_font(font6x8);
  TV.println(10,50,"ERROR LOW TEMP  "); 
  digitalWrite(BUZZER,HIGH); // Enable on
  while(digitalRead(RESETBTN)){}
}

void error_high()
{
  TV.select_font(font6x8);
  TV.println(10,50,"ERROR HIGH TEMP"); 
  digitalWrite(BUZZER,HIGH); // Enable on
  while(digitalRead(RESETBTN)){}
}


//int Read_time()
//{
//  return (millis() );
//}  


//int Cure_time()
//{
//  return millis()- base_t;
//}

void draw_axis() {
  TV.select_font(font4x6);
  TV.println(5,2,"Temp= ");
  TV.draw_line(2,2,2,96,INVERT);
  TV.draw_line(2,94,128,94,INVERT);
  TV.draw_line(12,94,12,96,WHITE);
    TV.draw_line(12,93,12,96,WHITE);
    TV.draw_line(24,93,24,96,WHITE);
    TV.draw_line(36,93,36,96,WHITE);
    TV.draw_line(48,93,48,96,WHITE);
    TV.draw_line(60,93,60,96,WHITE);
    TV.draw_line(72,93,72,96,WHITE);
    TV.draw_line(84,93,84,96,WHITE);
    TV.draw_line(96,93,96,96,WHITE);
    TV.draw_line(108,93,108,96,WHITE);
    TV.draw_line(128,93,128,96,WHITE);
  
    TV.draw_line(0,10,4,10,WHITE);
    TV.draw_line(0,20,4,20,WHITE);
    TV.draw_line(0,30,4,30,WHITE);
    TV.draw_line(0,40,4,40,WHITE);
    TV.draw_line(0,50,4,50,WHITE);
    TV.draw_line(0,60,4,60,WHITE);
    TV.draw_line(0,70,4,70,WHITE);
    TV.draw_line(0,80,4,80,WHITE);
    TV.draw_line(0,90,4,90,WHITE);

}


int Read_Temperature() {
  int value = 0;
  float temp;
  int temp_out;
  int samples = 10;
  float error_tc;

  digitalWrite(CS_TEMP,LOW);
  delay(2);
  digitalWrite(CS_TEMP,HIGH);
  delay(220);


  for (int i=samples; i>0; i--){
    digitalWrite(CS_TEMP,LOW); // Enable device
    /* Cycle the clock for dummy bit 15 */
    digitalWrite(SCK,HIGH);
    delay(1);
    digitalWrite(SCK,LOW);
    for (int i=11; i>=0; i--){
      digitalWrite(SCK,HIGH);  // Set Clock to HIGH
      value += digitalRead(SO) << i;  // Read data and add it to our variable
      digitalWrite(SCK,LOW);  // Set Clock to LOW
    }

    /* Read the TC Input inp to check for TC Errors */
    digitalWrite(SCK,HIGH); // Set Clock to HIGH
    error_tc = digitalRead(SO); // Read data
    digitalWrite(SCK,LOW);  // Set Clock to LOW

      for (int i=1; i>=0; i--) {
      digitalWrite(SCK,HIGH);
      delay(1);
      digitalWrite(SCK,LOW);
    }

    digitalWrite(CS_TEMP, HIGH); //Disable Device
  }

  value = value/samples;  // Divide the value by the number of samples to get the average
  temp = (value*0.25);  // Multiply the value by 25 to get temp in [ch730]C
  temp_out = temp;  // Send the float to an int (X10) for ease of printing.

  /* Output 9999 if there is a TC error, otherwise return 'temp' */
  if(error_tc != 0) { 
    return -1; 
  } 
  else { 
    return temp_out; 
  }
}