Friday, October 2, 2015

USB-CDC and HD44780 and DS18B20

Previously, I was learning about the USB-CDC communication and testing the Microchip Libraries for Application. I never really applying the code for my own use. So I was thinking to write something that transfer a string from PC to MCU and display it on HD44780; In addition, I was hoping to transfer string of data from MCU to PC. The idea is getting temperature from DS18B20, convert it to string, and send it to PC whenever I press a push button. While, from the PC side, I am intended to display the message that I have entered in PC terminal software.

To get started, I need to learn about one wire communication, and it turns out to be quit easy. The maxim website has detail descriptions and source code on implementation. There are quit a lot of documents, but the fundamental guide is this one.
It teaches the fundamental of one wire operations like:
write '1' bit
write '0' bit
read bit
and reset
*picture is taken from Maxim website.

After you get the basic idea, application note AN1199 from microchip can really helpful (because I am using the PIC18f). Best of all, it come with source code which compatible with C18, plus detail description of each function is included in AN1199.

Since the purpose is learning, I rewrite the whole source code to suit my own need by referring to microchip's code and some other tutorials I found on-line.

Continuing that, I need to learn the DS18B20 operation, there is one that suit my taste is from nicholas sirirak. Very detail guide and implementation, the best I found so far. Second best, the official datasheet. I read the nicholas sirirak tutorial, and refer back datasheet for part that I don't understand. So far, this approach work very good for me.

The simplest way of getting temperature data is single bus single sensor connection.
The steps are as follow:
1. Reset DS18B20
2. Write SKIP ROM command
3. Write CONVERT T command
4. Wait 750 millisecond or use polling
5. Reset DS18B20 again
6. Write SKIP ROM command
7. Write READ SCRATCHPAD command
8. Read  temperature

The implementation steps are found in the datasheet as follow:

The config can be simply ignored since we are not going to use it.

The DS18B20 actually sending the unsigned int temperature data in two bytes. So in the end, both bytes are combined to form one complete temperature data. The implementation code is as follow:

After that, we need to process the data into something readable.
By referring to table below,

we can see that last 4 bits are for decimal point, and bit 5 to bit 12 are for integer.

In order to process every data in integer format, I create a array that store the decimal point in integer format. Eliminating the floating point computation and save the ram memory.


4 bits maximum value equal to 16, and you take 1 divided by 16, you get the precision until 0.0625. When you pass the last 4 bits of temperature data, the decimal point is directly passed back. Save the computation effort by processing all data in integer.

Later, when I check the microchip cdc function file as shown below,

it seem that it is easier for me to convert the integer to array before passing to "putUSBUSART" function.

it is easy to process the positive temperature. However, for negative temperature, I need to one complement it, then add "one" like following:

temperature =~temperature ;
temperature =temperature +1;

then, the negative number is converted to positive number. 

Let take one example:
actual value                           |                   +10.125                 |                      -10.125
representation in binary        |        0000 0000 1010 0010      |           1111 1111 0101 1110
bitwise "NOT"                      |                         -                       |           0000 0000 1010 0001
add "1"                                  |                        -                        |         0000 0000 1010 0010

I think this process should be called "2nd complement" if I not mistaken.


After I was able to convert all numbers to array, I need to test it, just have the urge to test it.
For high temperature testing, I go and boil the water.


Well, the temperature is lower than I have expected. And it cool down so fast.

For less than zero temperature, I put some salt in water and put it in freezer until it almost frozen.
Finally, I get the negative temperature. My negative temperature conversion to positive temperature is proven to be correct.

To ensure the accuracy of the ds18b20, I need to compare the reading with a real temperature meter. This is where my multimeter come in - vc890c.

My most satisfied equipment so far, acceptable quality and functions with such low price. Come with a thermostat which has wide sensing range from -20 Celsius to 1000 Celsius.

It is a two ways comparison, if the reading is near, then I assume both devices are working good. Actually, it increase the level of confidence of me in China branded multimeter.

I compare the sensing in room temperature and in cold water, the reading is the same, vc890c precision is single digit, while the ds18b20 precision until 4 decimal points.


I have decent multimeter and working code of ds18b20.

Now it the transferring the data to PC. I am using my microchip MLA project file and start editing from that main file.

First include all the library files,

Go to the function - void UserInit(void) and include the lcd initialisation.


Later on, go to ProcessIO(void) and start editing from there.
I want to transmit temperature data each time I pressed a button.
So at the "if(buttonPressed)",
add this instruction "DS18B20_RawTempToBCD(DS18B20_Buffer, &length);".

I want each time I send a temperature data, it will start at new line. From ASCII code, new line code would be 0x0A, so I add 0x0A at end array by using this code "DS18B20_Buffer[length]=0x0A;".
After that, time to send the array using "putUSBUSART(DS18B20_Buffer,length+1);".
I add the 0x0A at the end of array, so I have to increase the DS18B20_Buffer by 1, so I add the length+1 at the putUSBUSART function.

Now, we need to take care of the data sent from PC to micrcontroller,
still in the ProcessIO(void) function,
Go to "if(USBUSARTIsTxTrfReady())", if the numBytesRead contains data, clear the lcd16x2 display,
then display the data at numBytesRead using this instruction "HD44780_WriteData(USB_Out_Buffer[i]);"

That all, from the microcontroller side.

For the PC side, I am using the Termite- Termite is an easy to use and easy to configure RS232 terminal, with an interface similar to that of "messenger" or "chat" programs.

The temperature data obtained is as follow,

At the Termite side, I type the string "hello world" and it is displayed in microcontroller side.

All the codes are shared in github.









No comments:

Post a Comment