Introduction: Scope Clock :Analog Clock and Temperature Sensor on an Oscilloscope

Scopeclock is an easy to use hardware to make your X-Y capable analog oscilloscope more useful .Using this simple to use hardware you can convert your analog oscilloscope into a scope clock.This project was me and my friend kshitij gupta at CEDT nsit under the guidance of Prof. Dhananjay V.Gadre.

Scope clock has two modes of operation

• Analog clock Mode –   This is the default mode of operation . When the arduino is reset an analog clock appears on the oscilloscope screen .It keeps accurate time using  clock hands.

• Temperature Mode –   This mode of operation displays the current temperature of the surrounding .

The mode is controlled  by a push button . On pressing and releasing the pushbutton an interrupt is generated which changes  the mode to Thermometer which displays the current temperature of the surrounding . After a few seconds the mode changes to  analog clock





Step 1: The D.A.C

A Digital-to-Analog converter (DAC or D-to-A) is a device that converts a digital (usually binary) code to an analog signal. Digital-to-analog conversion can degrade a signal, so conversion details are normally chosen so that the errors are negligible.
Due to cost and the need for matched components, DACs are almost exclusively manufactured on integrated circuits (ICs). There are many DAC architectures which have different advantages and disadvantages. The suitability of a particular DAC for an application is determined by a variety of measurements including speed and resolution. Depending upon the requirement we can use a 2 or more bit resolution DAC .

Although many types of DAC  configuration are available ,an R-2R Ladder is the  simple and inexpensive way to perform Digital-to-Analog conversion, using repetitive arrangements of precision resistor networks in a ladder-like configuration. In this project we have used two 8-bit R-2R ladder formations two convert the digital signal from the arduino into analog form and these are fed to the two channels of the Oscilloscope .


The DAC`s  are soldered on the  arduino protoshield  along with temperature sensor circuit , connections of the two DAC with pins of arduino are shown in schematic 

In our project digital pins D2-D9 are used in DAC1, digital pins D11-D13 and  analog pins A1-A5 are used in DAC2 .

Step 2: Temperature Sensor

First few important points while working with a thermistor.

A thermistor is a thermal resistor - a resistor that changes its resistance with temperature. Technically, all resistors are thermistors - their resistance changes slightly with temperature - but the change is usually very very small and difficult to measure. Thermistors are made so that the resistance changes drastically with temperature so that it can be 100 ohms or more of change per degree!

There are two kinds of of thermistors, NTC (negative temperature coefficient) and PTC (positive temperature coefficient). In general, you will see NTC sensors used for temperature measurement. PTC's are often used as resettable fuses - an increase in temperature increases the resistance which means that as more current passes through them, they heat up and 'choke back' the current, quite handy for protecting circuits!
Thermistors have some benefits over other kinds of temperature sensors such as analog output chips (LM35/TMP36 ) or digital temperature sensor chips (DS18B20) or thermocouples .

• First off, they are much much cheaper than all the above
• They are also much easier to waterproof since its just a resistor.
• They work at any voltage (digital sensors require 3 or 5V logic).
• Compared to a thermocouple, they don't require an amplifier to read the minute voltages - you can use any microcontroller to read a thermistor.
• They can also be incredibly accurate for the price. For example, the 10K 1% thermistor in the shop is good for measuring with ±0.25°C accuracy! (Assuming you have an accurate enough analog converter)
• They are difficult to break or damage - they are much simpler and more reliable
On the other hand, they require a little more work to interpret readings, and they dont work at very high temperatures like thermocouples. Without a digital-to-analog converter on board, you might be better off with a digital temperature sensor.


Scope clock has the following circuit for measuring temperature :-

Thermistor forms a voltage divider with a 10k  resistor .Voltage across the thermistor is fed to the analog pin A0 which constantly takes the analog voltage reading and sends it arduino .The thermistor is calibrated at about 28 o C. It measures the change in the temperature and we get the corresponding value displayed on the oscilloscope. On pressing and releasing the pushbutton an interrupt is generated on digital pin D10 connected to the ush button which changes  the mode to Temperature.Schematic is as given.

Step 3: Code

Code

#include <PinChangeInt.h>
#include <PinChangeIntConfig.h>
int  PIN = 10 ;       //pin at which interrupt is to be generated(pin connected to switch which when pressed will show temp on oscilloscope)

int thermistorpin=A0;    // which analog pin to connect  
int thermistornominal=150;     // resistance at 25 degrees C
int temperaturenominal=25;   // temp. for nominal resistance (almost always 25 C)
int numsamples =100;   // how many samples to take and average, more takes longer
                                  // but is more 'smooth'
int bcoefficient=3950;    // The beta coefficient of the thermistor (usually 3000-4000)
int seriesresistor=10000;     // the value of the 'other' resistor
int k;
int t1,t2;   //2 digits of temp
int samples[100];   //no. of samples to be taken by A0
int dacx[]= {
  9,8,7,6,5,4,3,2};//pins where 1st dac is connected
int dacy[]= {
  19,18,17,16,15,13,12,11};  //pins where 2nd dac is connected
int sec=90;      //controls second hand(90 is angle at 12 o'clock)
int mint=90;     //controls min hand
int hour=120;   //controls hour hand
float mincos=0;  //generates the value for sine and cos value for the end point of min hand
float minsin=1;
float hourcos=-0.866;   //generates the value for sine and cos value for the end point of hour hand
float hoursin=0.5;
//ponits (bit values) for sine and cos waves
unsigned char sinx[]=
{
  127,130,133,136,139,142,145,148,151,154,157,160,164,166,169,172,175,178,181,184,187,189,192,195, 197,200,202,205,207,210,212,214,217,219,221,223,225,227,229,231,232,234,236,237,239,240,242,
  243,244,245,246,247,248,249, 250,251,251,252,252,253,253,253,253,253,254,253,253,253,253,252,252,251, 251,250,249,249,248,247,246,245,243,242,241,239,238,236,235,233,231,230, 228,226,224,222,
  220,218, 215,213,211,209,206,204,201,199,196,193,191,188,185,182,180,177,174,171,168,165,162,159,156,153, 150,147,144,141,137,134,131,128,125,122,119,116,112,109,106,103,100,97,94,91,88,85,82,
  79,76, 73,71,68,65,62,60,57,54,52,49,47,44,42,40,38,35,33,31,29,27,25,23,22,20,18,17,15,14, 12,11,10,8,7,6,5,4,4,3,2,2,1,1,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,4,5,6,7,8,9,10,11,13,14,16,17,19,21,22,
  24, 26,28,30,32,34,36,39,41,43,46,48,51,53,56,58,61,64,66,69,72,75,78,81,84,87,89,93,96, 99,102,105,108,111,114,117,120,123,127
};
unsigned char cosx[]=
{
  254,253,253,253,253,252,252,251, 251,250,249,249,248,247,246,245,243,242,241,239,238,236,235,233,231,230, 228,226,224,222,220,218, 215,213,211,209,206,204,201,199,196,193,191,188,185,182,180,
  177,174,171,168,165,162,159,156,153, 150,147,144,141,137,134,131,128,125,122,119,116,112,109,106,103,100,97,94,91,88,85,82,79,76, 73,71,68,65,62,60,57,54,52,49,47,44,42,40,38,35,33,31,29,27,
  25,23,22,20,18,17,15,14, 12,11,10,8,7,6,5,4,4,3,2,2,1,1,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,4,5,6,7,8,9,10,11,13,14,16,17,19,21,22,24, 26,28,30,32,34,36,39,41,43,46,48,51,53,56,58,61,64,66,69,72,75,
  78,81,84,87,89,93,96, 99,102,105,108,111,114,117,120,123,127,130,133,136,139,142,145,148,151,154,157,160,164,166,169,172,175,178,181,184,187,189,192,195, 197,200,202,205,207,210,212,214,217,
  219,221,223,225,227,229,231,232,234,236,237,239,240,242,243, 244,245,246,247,248,249, 250,251,251,252,252,253,253,253,253,253,254
};
//sine and cosine value of angle at which 12 strokes of clock
float strokeSin[]=
{
  .0000,.5000,.8666,1.000,.8666,.5000,.0000,-.5000,-.8666,-1.000,-.8666,-.5000
};
float strokeCos[]=
{
  1.000,.8666,.5000,.0000,-.5000,-.8666,-1.000,-.8666,-.5000,.0000,.5000,.8666
};
unsigned long changeTime;// store program running time
void setup()
{
  pinMode(PIN, INPUT);     //set the 10th pin to input
  digitalWrite(PIN, HIGH); //use the internal pullup resistor
  PCintPort::attachInterrupt(PIN, swapMode,FALLING);
  for(int i=0;i<=7;i++)
  {
    pinMode(dacx[i],OUTPUT);  //declare dac's as output
    pinMode(dacy[i],OUTPUT);
  }
  changeTime=millis();
  displayclock();   //dispay "CLOCK BY"

  displayName();

}
void loop()
{
  minLine(127,127);    //function to display minute hand
  hourLine(127,127);   //function to display hour hand
  circle();    // function to make a circle
  strokes();  // function to add 12 stroke lines representing 12 hours in clock
  secLine(127,127,sec);
  if((millis()-changeTime)>114)
  {
    sec--;
    if(sec==0) sec=360;  //0 or 360 is angle at number three on clock
    if(sec==90) updateMin();  //when 60 sec are completed min hand is moved by 1 place
    changeTime=millis();
  }
}

// function to calculate and display temp.
//is called when interrupt is generated
void swapMode()
{

  uint8_t i;
  float average;
  // take N samples in a row, with a slight delay
  for (i=0; i< numsamples; i++) {
    samples[i] = analogRead(thermistorpin);
    delay(10);
  }
  // average all the samples out
  average = 0;
  for (i=0; i< numsamples; i++) {
    average += samples[i];
  }
  average /= numsamples;

  // convert the value to resistance
  average = 1023 / average - 1;
  average = seriesresistor / average;

  float steinhart;
  steinhart = average / thermistornominal;     // (R/Ro)
  steinhart = log(steinhart);                  // ln(R/Ro)
  steinhart /= bcoefficient;                   // 1/B * ln(R/Ro)
  steinhart += 1.0 / (temperaturenominal + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                 // Invert
  steinhart -= 273.15;                         // convert to C

  steinhart=round(steinhart);                  //gives us an whole number
  t1=steinhart/10;                             //generates number at tens place
  t2=(int)steinhart%10;                        //generates number at ones place
  for(int m=0;m<=100;m++)
  {
    //display the temp as for eg "35*C"
    font(t1,50);
    font(t2,100);
    degree(145);
    celcius(160);
  }
  sec-=19;
}
void updateMin()
{
  mint=mint-6;
  if(mint==0) mint=360;
  mincos=cos(PI*mint/180);
  minsin=sin(PI*mint/180);
  if(mint==90) updateHour;   //when 60 min are completed hour hand is moved by 1 place
}
void updateHour()
{
  hour=hour-30;
  if(hour==0) hour=360;
  hourcos=cos(PI*hour/180);
  hoursin=sin(PI*hour/180);
}
void point(int x,int y)   //plot a point on xy plane of oscilloscope
{
  for(int j=0;j<=7;j++)
  {
    digitalWrite(dacx[j],(( x & 1<<j)>0));
  }
  for(int j=0;j<=7;j++)
  {
    digitalWrite( dacy[j],(( y & 1<<j)>0));
  }
}
void parallely(int a,int b,int c)  //function to draw a line parallel to y axis(a is point constant on x axis and point on y axis varies from b to c)
{
  for(k=b;k<c;k=k+2)
  {
    point(a,k);
  }
}
void parallelx(int d,int e,int f)  //function to draw a line parallel to x axis(d is point constant on y axis and point on x axis varies from e to f)
{
  for(k=e;k<f;k=k+2)
  {
    point(k,d);
  }
}
void angleline (int x1,int y1,int x2,int y2)//draw a line between 2 points on oscilloscope
{
  for(int i=0;i<=200;i=i+4)
  {
    int x=x1+i*(x2-x1)/200;
    int y=y1+i*(y2-y1)/200;
    point(x,y);
  }
}
void circle()  //function to draw a circle
{
  for(int i=0;i<256;i=i+2) //send sin and cos waves to dacs
  {
    point(sinx[i],cosx[i]);
  }    
}
void strokes()
{
  for(int theta =0;theta <12;theta++ )
    for(int r=100;r<125;r=r+2)
    { 
      point(127+int(r*strokeCos[theta]),127+int(r*strokeSin[theta]));
    }
}
void  secLine(int x,int y ,int theta)   //function to draw seconds hand of length 'r',at an angle theta,x and y are starting points
{
  for(int r=0;r<127;r=r+2)
  {
    point(x+int(r*cos(PI*theta/180)),y+int(r*sin(PI*theta/180)));
  }
}
void  minLine(int x,int y)  //function to draw minute hand of length 'r',at an angle theta (given by global variables mincos and minsin),x and y are starting points
{
  for(int r=0;r<100;r=r+2)
  {
    point(x+int(r*mincos),y+int(r*minsin));
  }
}
void  hourLine(int x,int y)  //function to draw hour hand of length 'r',at an angle theta (given by global variables hourcos and hoursin),x and y are starting points
{
  for(int r=0;r<75;r=r+2)
  {
    point(x+int(r*hourcos),y+int(r*hoursin));
  }
}
void displayclock()  //display words "CLOCK BY"
{
  for(int f=0;f<=50;f++)
    //CLOCK
  { 
    parallely(10,135,195);  //C
    parallelx(135,10,50);
    parallelx(195,10,50);
    parallely(60,135,195);  //L
    parallelx(135,60,100);
    parallely(110,135,195);  //O
    parallely(150,135,195);
    parallelx(135,110,150);
    parallelx(195,110,150);
    parallely(160,135,195);  //C
    parallelx(135,160,200);
    parallelx(195,160,200);
    parallely(210,135,195);  //K
    angleline(210,165,245,195);
    angleline(210,165,245,135);
    //BY
    parallely(80,55,115);  //B
    angleline(80,115,120,100);
    angleline(80,85,120,100);
    angleline(80,85,120,70);
    angleline(80,55,120,70);
    angleline(130,115,155,95);//Y
    angleline(145,55,170,115);
  }
}
void displayName()  //display words "KSHITIJ AND KAPIL"
{
  for(int g=0;g<=40;g++)
  {
    //KSHITIJ
    parallely(5,95,155);  //K
    angleline(5,125,40,155);
    angleline(5,125,40,95);
    angleline(50,95,95,125);  //S
    parallelx(125,55,95);
    angleline(55,125,90,155);
    parallely(105,95,155);   //H
    parallely(145,95,155);
    parallelx(125,105,145);
    parallely(155,95,155);   //I
    parallely(185,95,155);   //T
    parallelx(155,165,205);
    parallely(215,95,155);  //I
    parallelx(155,225,252);  //J
    parallely(239,95,155);
    angleline(239,95,225,110); 
  }
  for(int f=0;f<=20;f++)
  {
    angleline(65,95,87,155);  //A
    angleline(110,95,87,155);
    parallelx(120,75,100);
    parallely(120,95,155);  //N
    angleline(120,155,165,95);
    parallely(165,95,155);
    parallely(175,95,155);  //D
    angleline(175,155,215,125);
    angleline(175,95,215,125);
  }
  for(int f=0;f<=40;f++)
  {
    //KAPIL
    parallely(10,95,155);  //K
    angleline(10,125,55,155);
    angleline(10,125,55,95); 
    angleline(65,95,87,155);  //A
    angleline(110,95,87,155);
    parallelx(120,75,100);
    parallely(120,95,155);  //P
    angleline(120,155,160,135);
    angleline(120,115,160,135);
    parallely(180,95,155);  //I
    parallely(200,95,155);  //L
    parallelx(95,200,245);
  }
}
void font(int a,int x) //function to display 2 numbers of temp
{
  switch(a)
  { 
  case 0:
    parallelx(40,x,x+40);
    parallelx(110,x,x+40);
    parallely(x,40,110);
    parallely(x+40,40,110);
    break;
  case 1:
    parallely(x+20,40,110);
    break;
  case 2:
    parallelx(110,x,x+40);
    parallelx(75,x,x+40);
    parallelx(40,x,x+40);
    parallely(x+40,75,110);
    parallely(x,40,75); 
    break;
  case 3:
    parallelx(110,x,x+40);
    parallelx(75,x,x+40);
    parallelx(40,x,x+40);
    parallely(x+40,40,110);
    break;
  case 4:
    parallely(x,80,110);
    parallely(x+40,40,110);
    parallelx(80,x,x+40);
    break;
  case 5:
    parallelx(110,x,x+40);
    parallelx(75,x,x+40);
    parallelx(40,x,x+40);
    parallely(x,75,110);
    parallely(x+40,40,75); 
    break;
  case 6:
    parallelx(110,x,x+40);
    parallelx(75,x,x+40);
    parallelx(40,x,x+40);
    parallely(x,40,110);
    parallely(x+40,40,75); 
    break;
  case 7:
    parallely(x+40,40,110);
    parallelx(110,x,x+40);
    break;
  case 8:
    parallelx(110,x,x+40);
    parallelx(75,x,x+40);
    parallelx(40,x,x+40);
    parallely(x,40,110);
    parallely(x+40,40,110); 
    break;
  case 9:
    parallelx(110,x,x+40);
    parallelx(75,x,x+40);
    parallelx(40,x,x+40);
    parallely(x,75,110);
    parallely(x+40,40,110); 
    break; 
  }       
}
void degree(int x)  //display circle of degree
{
  parallelx(110,x,x+10);
  parallelx(100,x,x+10);
  parallely(x,100,110);
  parallely(x+10,100,110);
}
void celcius(int x)  //display "C"
{
  parallelx(110,x,x+40);
  parallelx(40,x,x+40);
  parallely(x,40,110);
}

Comments

author
Eucalypto made it! (author)2016-11-09

Hey! Nice project...I want to make one...but where can I find the arduino libraries?

author
SteveMann made it! (author)2016-02-08

Beautiful!

It would look nice on a 'scope with a round screen!

author
g4ipz made it! (author)2014-08-16

Out of interest have you considered including an RTC into the device to keep the clock running on time?

author
robot797 made it! (author)2014-08-03

am i free to rewrite your code?

About This Instructable

11,782views

7favorites

License:

Bio: I am the Technology lover always doing intersting and innovative stuff. Subscribing to me = fun + excitement !!!!!!!!!. Please check my Website if you want to learn ... More »
More by kapil gupta:LED Flash Light Android Application RC MOOD LYTELED Dot Matrix Display
Add instructable to: