convert a decimal value to its binary representation ( string )

Wanted to share this snippet of code which I used to display a decimal numbers binary representation. It is quite self explanatory and easy to understand.

/**
  * Turns a decimal value to its binary representation
  */
char* dec2binWzerofill(unsigned long Dec, unsigned int bitLength){
    return dec2binWcharfill(Dec, bitLength, '0');
}

char* dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill){
  static char bin[64];
  unsigned int i=0;
unsigned int j;
  while (Dec > 0) {
    bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill;
    Dec = Dec >> 1;
  }

  for ( j = 0; j< bitLength; j++) {
    if (j >= bitLength - i) {
      bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
    }else {
      bin[j] = fill;
    }
  }
  bin[bitLength] = '';

  return bin;
}
 

Pic based temperature sensor with 7 segment display and ds18b20

This circuit is a Digital Temerature Sensor using a Dallas ‘1-wire’ DS18B20 Digital Thermometer


Firstly I would like to thank Pommie and Mike, K8LH from the Electro Tech Online Forum for their genourous help. This has been the most challenging project to date and they have helped immensely. They have tought me many valuable lessons about programming in Assembly language and it has really assitsted me in getting this project up and running.

Note: I would like to make a point that some snippets of their own code is used in this program. I have used it with their permission and please observe any copyrights or name recognition placed in the code. If you wish to use their snippets of code, please contact them via the Electro-Tech-Online forum.

How It Works

The DS18B20 is a direct-to-digital temperature sensor using Maxim’s exclusive 1-Wire bus protocol that implements bus communication using one control signal. In regards to hardware, this particular sensor is particularly easy to interface to. It only requires 1 external pull-up resistor to operate as opposed to an analogue sensor which possibly needs multiple external components such as resistors and op-amps.

In regards to software, opposed to analogue sensors, the Dallas 1-wire digital sensors are arguably as easy to interface to. While an analogue sensor will need an Analogue to Digital conversion using a voltage reference and possibly using an op-amp, the Dallas 1-wire direct to digital sensors require precise timing when it comes to communication. This program is fairly basic in principle as all it does is obtain temperature data from the DS18B20 sensor and display the temperature in Degrees Celsius on a 4 digit, 7 segment display. But when it comes to actually doing this, as you will see from the .ASM file, it is more complicated than it sounds. In words; the program first initialises the PIC16F628A Microcontroller. It assigns the Inputs and Outputs, zero’s all bank 0 RAM, initialises the display column select bit and configures TIMER 2. TIMER 2 is used to interrupt the normal loop of the program to update the 7 segment LED display.

After the Microcontroller has been setup, it begins communication with the DS18B20 Temperature Sensor. Communication routines take up just under half of the program memory. After the temperature has been gathered and stored in RAM, the Microcontroller takes the 12-bit signed/fraction integer and converts it into a decimal number then stores it in four general purpose registers in RAM.

For example, take the number D’95.8′. It is stored like this:

HUNS register = 0
TENS register = 9
ONES register = 5
TENTHS register = 8

These registers are then used within the Interrupt Service Routine to call a table to obtain display data.
The program runs continuously, updating the temperature on the display just over once per 1 second.

Features Summary:

  • Temperature data gathered more than once per second.
  • TIMER 2 interrupt driven display.
  • Program expandable to include multiple sensors on the same 1-Wire bus.
  • Temperature range of -55.0 – 127.9 Degrees Celsius.

Please see the DS18B20 Datasheet for detailed information on the device.

schematicbreadboard

 

 

digitaltemperaturesensorbasic.zip

Here is the complete project   (with explanation , code, schematic and video)

 

Keeping track of time in embedded applications: millis();

Its very handy to keep track of time in embedded programs. In this post I will implement a function called millis() which can be used to track time.  Arduino users will be familiar with this one. I would be doing it for AVR MCUs you can easily port it for others. this function returns the number of milliseconds since the MCU began running the current program. This number will overflow (go back to zero), after approximately 50 days.
It uses a hardware timer , in this post i will use timer0 . The first step is to initialize timer0 and interupts. lets start.

void timer0(){
  // To set clock:
  // 1MHZ is 1,000,000 ticks per second
  // 1000 milli in 1 second
  // xMHZ = 1000millis
  // so MHZ/millis gives # HZ per millis
  // (HZ/millis)/prescaler= Top counter number

  // EG:for 8MHZ clock
  // 8000000/1000
  // 8000.0000000000
  // 8000/256
  // 31.2500000000 TOP counter

  //set CTC (clear timer on compare match mode)
  TCCR0A = (1< <WGM01);
  //sets prescaler clkIO/256  ***THIS MIGHT CAUSE ISSUES SETS FOR ALL CLOCKS**!!!!
  TCCR0B = (1<<CS02);
  //sets interrupt enable for OCF0A (TIMER_COMPA_vect)
  TIMSK0 = (1<<OCIE0A);
  //sets TOP counter match A at 31
  OCR0A = 31;
}


volatile uint32_t millis()
{
 uint32_t mill;
 uint8_t oldSREG = SREG;
 // remember last value of interrupts
 // disable interrupts while we read timer0_millis or we might get an
 // inconsistent value (e.g. in the middle of a write to timer0_millis)
 cli();
 mill = millis_count;
 SREG = oldSREG; // rewrite reg value to turn back on interrupts
 return mill;
}

In the code shown above we have initialized timer/counter 0 to make an interrupt after every millisecond. Next we have to update our millisecond count.

//interrupt declaration
ISR(TIMER0_COMPA_vect)
{
  ++millis_count;
  //OCR0A = 10; //sets upper breakpoint A
}

That’s it. Lets see how to use it! First we copy the current value in milis() to a variable.

uint32_t starttime=millis();

and later we compare the new values with the start value. Here’s an example of a 25 second.

if(millis()-starttime > 25000)
{
  // some code here
}

Note that the parameter for millis() is an unsigned long, errors may be generated if a programmer tries to do math with other datatypes such as ints.

There are a number of ways you can use this. Hope this post will help you

 

function to return binary equivalent of an int in a string format

On request of Shamas Akhtar Awan :
This is the function to return a string of binary equivalent of an int. The function takes in an integer value and returns a string of 0′s and 1′s of binary equavalet of that integer.

char * int2binarystr(int value) {
    char binstr[23];// adjust the size of the string to your needs
    int i,b;
    b=value;
    i=0;
    while(b>0)
    {
        binstr[i]=b%2;
        b=b/2; i++;
    }
    binstr[i]=00;
    return binstr; // returns the string
}

You can use this in your code as needed. One example is to write to uart the string

Uart0_write_text(int2binarystr(20)); // writes the string conataing the binary equavalent of 20 to uart