{"id":773,"date":"2026-03-17T15:22:30","date_gmt":"2026-03-17T15:22:30","guid":{"rendered":"https:\/\/odonodesign.com\/blog\/?p=773"},"modified":"2026-03-28T17:59:57","modified_gmt":"2026-03-28T17:59:57","slug":"tinytherm-v2-0-pic16f628-digital-thermometer-firmware-full-build-package-ds18b20-assembly-language","status":"publish","type":"post","link":"https:\/\/odonodesign.com\/blog\/2026\/03\/17\/tinytherm-v2-0-pic16f628-digital-thermometer-firmware-full-build-package-ds18b20-assembly-language\/","title":{"rendered":"TINYTherm V2.0 PIC16F628 Digital Thermometer Firmware + Full Build Package (DS18B20, Assembly Language)"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"682\" src=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2024\/05\/image0-1024x682.jpeg\" alt=\"\" class=\"wp-image-685\" srcset=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2024\/05\/image0-1024x682.jpeg 1024w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2024\/05\/image0-300x200.jpeg 300w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2024\/05\/image0-768x512.jpeg 768w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2024\/05\/image0-1536x1024.jpeg 1536w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2024\/05\/image0.jpeg 1547w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"503\" src=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/Thermometer-7-segment-1024x503.jpg\" alt=\"\" class=\"wp-image-789\" srcset=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/Thermometer-7-segment-1024x503.jpg 1024w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/Thermometer-7-segment-300x147.jpg 300w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/Thermometer-7-segment-768x377.jpg 768w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/Thermometer-7-segment-1536x755.jpg 1536w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/Thermometer-7-segment-2048x1006.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Hello, the much loved Seven Segment Digital Thermometer has been improved upon! This is version 2.0 of TINY Therm. It basically improves its brightness and by driving the display directly from the power rails using 2 transistors. I\u2019ve also included a button so that it will stay asleep and only wake to show the temperature when pressed, then go back to sleep, conserving battery power. This will allow 3 AAA batteries to last for years without changing them! This is a nice bright display now so that it is much better than unlit lcds on the market that are hard to see from afar!<\/p>\n\n\n\n<p>So let&#8217;s dive straight in. I&#8217;m going to emit most of what was spoken about in the previous post regarding this product. Instead I&#8217;m going to just dive straight in and give you the schematics, gerber and drill files to upload direct to JLCPCB.com, and the components Bill of materials list. I&#8217;ll also give you the assembly language code here too. <\/p>\n\n\n\n<p>I&#8217;ll update here with a 3D Print file of a nice casing for it when I get the first prototype PCB&#8217;s back to populate myself and demo here.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>The schematic looks like this:<\/p>\n\n\n\n<div data-wp-interactive=\"core\/file\" class=\"wp-block-file\"><object data-wp-bind--hidden=\"!state.hasPdfPreview\" hidden class=\"wp-block-file__embed\" data=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/Thermometer-7-segment.pdf\" type=\"application\/pdf\" style=\"width:100%;height:600px\" aria-label=\"Embed of Thermometer 7 segment.\"><\/object><a id=\"wp-block-file--media-e2b65c99-378a-4d8a-a521-ae06d8e0af70\" href=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/Thermometer-7-segment.pdf\">Thermometer 7 segment<\/a><a href=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/Thermometer-7-segment.pdf\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-e2b65c99-378a-4d8a-a521-ae06d8e0af70\">Download<\/a><\/div>\n\n\n\n<p>Components bill of materials list:<\/p>\n\n\n\n<p>You can buy most of these from AliExpress, Amazon or eBay for pennies. Please support my blog by purchasing from these links below:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"https:\/\/s.click.aliexpress.com\/e\/_DEl17cB\">PIC16F628 04\/P (ensure its the 4 Mhz version, denoted by the 04\/P)<\/a><\/li>\n\n\n\n<li>Dual <a href=\"https:\/\/s.click.aliexpress.com\/e\/_DCa4pzZ\">7 Segment Display (common anode). Not common cathode.<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/s.click.aliexpress.com\/e\/_DnCJUrZ\">DS18B20<\/a> (also on <a href=\"https:\/\/amzn.to\/4gpOVUF\" target=\"_blank\" rel=\"noreferrer noopener\">Amazon<\/a>)<\/li>\n\n\n\n<li><a href=\"https:\/\/s.click.aliexpress.com\/e\/_DdelBxH\">0.1uF ceramic capacitor,<\/a> <a href=\"https:\/\/s.click.aliexpress.com\/e\/_Dkpa5Pz\">a few resistors per the schematic (bought in one assortment pack)<\/a><\/li>\n\n\n\n<li>New components for vs 2.0: <a href=\"https:\/\/s.click.aliexpress.com\/e\/_EzjT1FI\" target=\"_blank\" rel=\"noreferrer noopener\">2 x 2N3906 transistors<\/a><\/li>\n<\/ol>\n\n\n\n<p>Now, the assembly language code to flash the pic with can be seen here. I used MPLab 8.92 as that&#8217;s the latest version on windows that uses mpasm before they upgraded to MPLab X. I much prefer the old mpasm as it&#8217;s much simpler and usable for product design.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>;**********************************************************************\n;   This file is a basic code template for object module code         *\n;   generation on the PIC16F628. This file contains the               *\n;   basic code building blocks to build upon.  As a project minimum   *\n;   the 16F628.lkr file will also be required for this file to        *\n;   correctly build. The .lkr files are located in the MPLAB          *  \n;   directory.                                                        *\n;                                                                     *\n;   If interrupts are not used all code presented between the         *\n;   code section \"INT_VECTOR and code section \"MAIN\" can be removed.  *\n;   In addition the variable assignments for 'w_temp' and             *\n;   'status_temp' can be removed.                                     *                         \n;                                                                     *\n;   If interrupts are used, as in this template file, the 16F628.lkr  *\n;   file will need to be modified. Refer to the readme.tmp file for   *\n;   this information.                                                 *\n;                                                                     *\n;   Refer to the MPASM User's Guide for additional information on     *\n;   features of the assembler and linker (Document DS33014F).         *\n;                                                                     *\n;   Refer to the respective PIC data sheet for additional            *\n;   information on the instruction set.                               *\n;                                                                     *\n;   Template file built using MPLAB V4.00 with MPASM V2.20.12 and     *\n;   MPLINK 1.20.10 as the language tools.                             *\n;                                                                     *\n;**********************************************************************\n;                                                                     *\n;    Filename:\t    xxx.asm                                           *\n;    Date:                                                            *\n;    File Version:                                                    *\n;                                                                     *\n;    Author:                                                          *\n;    Company:                                                         *\n;                                                                     * \n;                                                                     *\n;**********************************************************************\n;                                                                     *\n;    Files required:                                                  *\n;                                                                     *\n;                                                                     *\n;                                                                     *\n;**********************************************************************\n;                                                                     *\n;    Notes:                                                           *\n;                                                                     *\n;                                                                     *\n;                                                                     *\n;                                                                     *\n;**********************************************************************\n\n\n\tlist      p=16f628            ; list directive to define processor\n\t#include &lt;p16f628.inc&gt;        ; processor specific variable definitions\n\t\n\t  __CONFIG\t_CP_OFF&amp;_BODEN_OFF&amp;_PWRTE_ON&amp;_WDT_OFF&amp;_LVP_OFF&amp;_MCLRE_OFF&amp;_INTRC_OSC_NOCLKOUT \n; PWRTE_ON enables power up timer delay ~72ms which should help screen to self initialise\n\n; '__CONFIG' directive is used to embed configuration data within .asm file.\n; The labels following the directive are located in the respective .inc file.\n; See respective data sheet for additional information on configuration word.\n\n\n\n\n\n\n;***** VARIABLE DEFINITIONS (examples)\n\n; example of using Shared Uninitialized Data Section\nINT_VAR       UDATA_SHR   \nw_temp        RES     1           ; variable used for context saving \nstatus_temp   RES     1           ; variable used for context saving\n\n\n; example of using Uninitialized Data Section\nTEMP_VAR      UDATA      0x20     ; explicit address specified is not required\ntemp_count    RES     1           ; temporary variable (example)\n\n\n; example of using Overlayed Uninitialized Data Section\n; in this example both variables are assigned the same GPR location by linker\nG_DATA        UDATA_OVR           ; explicit address can be specified\nflag          RES     1           ; temporary variable (shared locations - G_DATA)\n\nG_DATA        UDATA_OVR   \ncount         RES     1           ; temporary variable (shared locations - G_DATA)\n\n\n\n\n\n\n;**********************************************************************\nRESET_VECTOR  CODE    0x000       ; processor reset vector\n\ngoto   start              ; go to beginning of program\n\n\n\t    \n\nINT_VECTOR   CODE    0x004        ; interrupt vector location\n\t\tgoto INTERRUPT\nMAIN        CODE\n\n\n;===========================================================\n; Lookup table (0 = ON, common anode)\n;===========================================================\nDigitToSeg\nADDWF PCL,F\nRETLW b'00000001'   ; 0\nRETLW b'01010111'   ; 1\nRETLW b'01001000'   ; 2\nRETLW b'01000100'   ; 3\nRETLW b'00010110'   ; 4\nRETLW b'00100100'   ; 5\nRETLW b'00100000'   ; 6\nRETLW b'01000111'   ; 7\nRETLW b'00000000'   ; 8\nRETLW b'00000110'   ; 9\n\nINTERRUPT\nretfie\n\n\nLOOP\t\tEQU\t0X20\t;DELAY LOOP\nLOOP1\t\tEQU\t0X21\t;DELAY LOOP\nCOUNT\t\tEQU\t0X22\nO_BYTE\t\tEQU\t0X23\nI_BYTE\t\tEQU\t0X24\nFLAGS\t\tEQU\t0X25\nCALC_CRC\tEQU\t0X26\t;CALCULATED CRC\nBCOUNT\t\tEQU\t0X27\nTEMP1\t\tEQU\t0X28\t;TEMP MEMORY DURING CALC_CRC\nTEMP2\t\tEQU\t0X29\t;TEMP MEMORY DURING CALC_CRC\n\n;SCRATCHPAD IS READ INTO 0X2A - 0X32\nTEMP_LSB\tEQU\t0X2A\nTEMP_MSB\tEQU\t0X2B\nTH\t\tEQU\t0X2C\nTL\t\tEQU\t0X2D\nRES1\t\tEQU\t0X2E\nRES2\t\tEQU\t0X2F\nC_REMAIN\tEQU\t0X30\nC_PERC\t\tEQU\t0X31\nCRC\t\tEQU\t0X32\nUNITS\t\tequ\t0x38\nTENS\t\tequ\t0x39\n\n\n\n;pats variables\n\t\tcount1 \t\tequ 0x40\t;used in delay routine\n\t\tcounta \t\tequ 0x41\t;used in delay routine \n\t\tcountb \tequ 0x42\t\t;used in delay routine\n\t\tSUBCHECK equ 0x43\n\t\tcounter \tequ 0x44\t\t;used in 2 digit display routine to switch between the two digits many times before exiting the loop so that the user can get some time to view the digits\n        SEGIT equ 0x45\n\t\tSEGIT2 equ 0x46\n\t\tSAVEWR EQU 0X47\n\t\tFILE1 equ 0x48\n\t\tFILE2 equ 0x49\n\t\tFILE3 equ 0x50\n\t\t\n\t\tTENS_Split equ 0x51\n        UNITS_Split equ 0x52\n        TEMP equ 0x53\n\t\tCombinedByte equ 0x54\n\t\tLSB_Sanitise equ 0x55\n\t\tMSB_Sanitise equ 0x56\n\t\ttemp equ 0x57\n\t\tTENS_AGAIN equ 0x58\n\t\tUNITS_AGAIN equ 0x59\n\n\n\n\n;FLAGS BITS\nPRESENCE\tEQU\t.0\t;PRESENCE\nDS_ERROR\tEQU\t.1\t;CRC ERROR\n\n;DS1820 BITS\nDQ_BIT\t\tEQU\t0\n#DEFINE\t\tDQ\tPORTA,DQ_BIT\n#DEFINE\t\tTRIS_DQ\tTRISA,DQ_BIT\n\n\nstart\t\t;Reset vector\n\n\tgoto\tSTART_OF_PROG\n\nINITIALISE\n\nmovlw 0x07\nmovwf CMCON ; turn off comparitors so can use porta as digital i\/o\n\tclrf\tPORTB\n\tbsf\tSTATUS,RP0\t; Change to bank 1\n\tmovlw\tb'00000000'\t; Set PORTB as digital output\n\tmovwf\tTRISB\t\t; Set data \/ control lines to Output\nmovlw b'00000000'\nmovwf TRISA ; Set PORTA as an output, but the DQ line will need to be both input and output at different times, which is toggled later in the program for the DS18B20 to communicate effectively\n\tbcf\tSTATUS,RP0\t; Go back to bank 0\n\nbsf PORTA, 0 ; Ensure RA0 high initially (bus idles high via pull-up) as per ChatGPT suggestion\n\n\n\n;setting up the timer0 function for isr NO LONGER NEEDED AS USING PCL\n\n\n\n\treturn\n\n\nSTART_OF_PROG\n\n\tcall\tINITIALISE\t\t; Set up port and screen\n\n\tnop\t\t; not actually needed but gives me somewhere to RUN TO or insert BREAK\n\n;\tLCD_STRING\thello_world\t; Use Macro to send string from lookup table to LCD\n\n\tnop\t\t; not actually needed but gives me somewhere to RUN TO or insert BREAK\n\n;\tLCD_STRING\tuser_defs\t; Define \"graphics\" characters\n\n\tnop\t\t; not actually needed but gives me somewhere to RUN TO or insert BREAK\n\n\n\nGogo\n\t;call\tconvert\n    ;movlw .25\n    ;bcf STATUS, Z\n    ;subwf TEMP_LSB, 1\n    ;BTFSS\tSTATUS,Z\n    ;call temp_low\n    ;btfsc STATUS, Z\n    ;call temp_high\n    ;call display\nBCF INTCON, GIE ; disable all interrupts\ncall READ_SCRATCHPAD\ncall SEGGY\n\n\n\tgoto\tGogo\n\n\n\n;*******************************************************************************************\n\nREAD_SCRATCHPAD\n;READ SCRATCHPAD, CHECK PRESENCE &amp; CRC\n\tBCF\tFLAGS,DS_ERROR\n\tCALL\tDS_RESET ;THIS IS THE INITIALIZATION ROUTINE\n\tBTFSS\tFLAGS,PRESENCE\n\tRETURN\t\t\t;NOT PRESENT\n\n\tMOVLW\t0XCC\t\t;SKIP ROM. THIS MEANS THE FOLLOWING COMMAND WILL ADDRESS ALL SLAVES ON THE LINE.\n\tCALL\tOUT_BYTE\n\tMOVLW\t0X44\t\t;CONVERT TEMP\n\tCALL\tOUT_BYTE\n\n\tCALL\tPASSIVE_WAIT_CONVERSION ;WAITS WHILE DS18S20 CONVERTS TEMPERATURE A-D\n\n;\tCALL\tWAIT_CONVERSION\t\t;CAN BE LONG _ DO OTHER THINGS?\n\n\tCALL\tDS_RESET\n\tBTFSS\tFLAGS,PRESENCE\n\tRETURN\t\t\t;NOT PRESENT\n\n\tMOVLW\t0XCC\t\t;SKIP ROM\n\tCALL\tOUT_BYTE\n\tMOVLW\t0XBE\t\t;READ SCRATCHPAD\n\tCALL\tOUT_BYTE\n\n\tCLRF\tCALC_CRC\n\tMOVLW\tTEMP_LSB\t;ADDRESS TO STORE TEMP_LSB\n\tMOVWF\tFSR\n\tMOVLW\t.9\t\t;READ 9 BYTES FROM SCRATCHPAD\n\tMOVWF\tBCOUNT\n\nNEXT_CODE\n\tCALL\tIN_BYTE\n\tMOVWF\tINDF\n\tMOVWF\tTEMP1\n\tMOVLW\t.8\n\tMOVWF\tCOUNT\t\t;8 BITS PER BYTE\n\tINCF\tFSR,F\n\tDECFSZ\tBCOUNT,F\n\tGOTO\tDO_CRC\n\tMOVF\tTEMP1,W\n\tSUBWF\tCALC_CRC,W\t;Z WILL BE SET IF CRC CORRECT\n\tBTFSS\tSTATUS,Z\n\tBSF\tFLAGS,DS_ERROR\t;CRC WAS NOT CORRECT\n\tRETURN\nDO_CRC\n\tMOVF\tCALC_CRC,W\n\tXORWF\tTEMP1,W\n\tMOVWF\tTEMP2\t\t;STORE IN TEMP LOCATION THAT CAN BE ROTATED INTO C\n\tRRF\tTEMP1,F\t\t;ROTATE DATA READY FOR NEXT BIT\n\tRRF\tTEMP2,W\n\tBTFSS\tSTATUS,C\n\tGOTO\tNO_CARRY\n\tMOVLW\t0X18\n\tXORWF\tCALC_CRC,F\nNO_CARRY\n\tRRF\tCALC_CRC,F\n\tDECFSZ\tCOUNT,F\n\tGOTO\tDO_CRC\n\tGOTO\tNEXT_CODE\n\n\n;-----------------------------------------------------\n\nDS_RESET\n; RESET DS1820 _ CHECK FOR PRESENCE PULSE!\n\tBCF\tFLAGS,PRESENCE\n\tCALL\tPIN_LO\n\tMOVLW\t.48\n\tCALL\tDELAY_10US\t;48 X 10US ~480US\n\tCALL\tPIN_HI\n\tMOVLW\t.6\n\tCALL\tDELAY_10US\t;6 X 10US ~60US\n\tBTFSS\tDQ\t\t;CHECK PRESENCE PULSE\n\tBSF\tFLAGS,PRESENCE\t;PRESENT\n\tMOVLW\t.42\n\tCALL\tDELAY_10US\t;42 X 10US ~420US\n\tRETURN\n\n;------------------------------------------------------\n\nPIN_LO\n\tBCF\tDQ\t\t;SET DATA PIN LOW, DO ONCE INITIALLY ?\n\tBSF\tSTATUS,RP0\t;SAFEST THIS WAY _ OTHER CODE MAY ACCIDENTLY CHANGE DQ?\n\tBCF\tTRIS_DQ\t\t;SET DATA PIN AS OUTPUT\n\tBCF\tSTATUS,RP0\n\tRETURN\n\n;------------------------------------------------------\nPIN_HI\n\tBSF\tSTATUS,RP0\n\tBSF\tTRIS_DQ\t\t;SET DATA AS INPUT WITH PULL UP!!!\n\tBCF\tSTATUS,RP0\n\tRETURN\n\n;------------------------------------------------------\nOUT_BYTE\n\tMOVWF\tO_BYTE\n\tMOVLW\t.8\n\tMOVWF\tCOUNT\nOUT_BYTE_1\n\tRRF\tO_BYTE,F\n\tBTFSS\tSTATUS,C\n\tGOTO\tOUT_0\n\tGOTO\tOUT_1\nOUT_BYTE_2\n\tDECFSZ\tCOUNT,F\n\tGOTO\tOUT_BYTE_1\n\tRETURN\n\nOUT_0\n\tCALL\tPIN_LO\n\tMOVLW\t.6\t\t;60US DELAY\n\tCALL\tDELAY_10US\n\tCALL\tPIN_HI\n\tGOTO\tOUT_BYTE_2\n\nOUT_1\n\tCALL\tPIN_LO\t\t;MOMENTARY _ LONGISH!\n\tCALL\tPIN_HI\n\tMOVLW\t.6\t\t;60US DELAY\n\tCALL\tDELAY_10US\n\tGOTO\tOUT_BYTE_2\n\n;------------------------------------------------------\nIN_BYTE\n\tMOVLW\t.8\n\tMOVWF\tCOUNT\n\tCLRF\tI_BYTE\nIN_BYTE_1\n\tCALL\tPIN_LO\t\t;3US\n\tNOP\t\t\t;4US\n\tCALL\tPIN_HI\t\t;11US\n\tNOP\t\t\t;12US\n\tBCF\tSTATUS,C\t;13US\n\tBTFSC\tDQ\t\t;14US SAMPLE NEAR END OF 15US\n\tBSF\tSTATUS,C\n\tRRF\tI_BYTE,F ;ROTATES IN THE CARRY BIT... EITHER 1 OR ZERO DEPENDING ON THE BTFSC DQ INSTRUCTION\n\tMOVLW\t.4\t\t;40US + EXTRAS _ MIN OF 45US\n\tCALL\tDELAY_10US\n\tDECFSZ\tCOUNT,F\n\tGOTO\tIN_BYTE_1\n\tMOVF\tI_BYTE,W\n\tRETURN\n\n;------------------------------------------------------\nWAIT_CONVERSION\n;WAIT END OF CONVERSION WHILE ACTIVELEY POWERED\n\tBCF\tDQ\t\t;SET DATA PIN LOW  ?? DO ONCE INITIALLY ??\n\tBSF\tSTATUS,RP0\t\n\tBCF\tTRIS_DQ\t\t;SET DATA PIN AS OUTPUT _ 0\n\tNOP\t\t\t;1US\n\tBSF\tTRIS_DQ\t\t;SET AS DATA AS INPUT WITH PULL UP!!!\n\tBCF\tSTATUS,RP0\t;3US\n\tGOTO\t$+1\t\t;5US\n\tGOTO\t$+1\t\t;7US\n\tGOTO\t$+1\t\t;9US\n\tGOTO\t$+1\t\t;11US\n\tGOTO\t$+1\t\t;13US\n\tBTFSC\tDQ\t\t;14US SAMPLE NEAR END OF 15US\n\tGOTO\tCONV_FINISHED\n\tMOVLW\t.6\t\t;40US + EXTRAS _ MIN OF 45US\n\tCALL\tDELAY_10US\n\tGOTO\tWAIT_CONVERSION\nCONV_FINISHED\n\tMOVLW\t.4\t\t;40US + EXTRAS _ MIN OF 45US\n\tCALL\tDELAY_10US\n\tRETURN\t\n\n;------------------------------------------------------\nPASSIVE_WAIT_CONVERSION\n;WAIT END OF CONVERSION WHILE PASSIVELEY POWERED\n;ALSO WORKS WHILE POWERED\n;MUST DRIVE DQ HIGH DURING CONVERSION\n\n\tBSF\tDQ\n\tBSF\tSTATUS,RP0\n\tBCF\tTRIS_DQ\t\t;DRIVE HIGH\n\tBCF\tSTATUS,RP0\n\n\tMOVLW\t.4\t\t;4 * ~0.2S = ~800MS\n\tMOVWF\tCOUNT\n\tCALL\tDELAY\n\tDECFSZ\tCOUNT,F\n\tGOTO\t$-2\n\n\tBSF\tSTATUS,RP0\n\tBSF\tTRIS_DQ\t\t;FLOAT HIGH\n\tBCF\tSTATUS,RP0\n\tBCF\tDQ\n\tRETURN\n\n;------------------------------------------------------\nDELAY\n\tCLRF\tLOOP\t\t; ~ 0.2S DELAY (~256 X 256 X 3 US)\n\tCLRF\tLOOP1\nENCORE\n\tDECFSZ\tLOOP,F\n\tGOTO\tENCORE\n\tDECFSZ\tLOOP1,F\n\tGOTO\tENCORE\n\tRETURN\n\n;------------------------------------------------------\nDELAY_10US\n\tMOVWF\tLOOP1\nDELAY_10US_1\n\tNOP\n\tNOP\n\tNOP\n\tNOP\n\tNOP\n\tNOP\n\tNOP\n\tDECFSZ\tLOOP1,F\n\tGOTO\tDELAY_10US_1\n\tRETURN\n\n;*******************************************************************************************\n\n\n\nRE_READ\n\tCALL\tREAD_SCRATCHPAD\n\tBTFSS\tFLAGS,PRESENCE\n\tGOTO\tNOT_PRESENT\n\tBTFSC\tFLAGS,DS_ERROR\n\tGOTO\tREAD_ERROR\n\n\tMOVF\tTEMP_MSB,F\n\tBTFSS\tSTATUS,Z\n\tGOTO\tNEGATIVE\n\n\tBCF\tSTATUS,C\n\tRRF\tTEMP_LSB,F\n\t\t\t\t;TEMP_LSB IS DECIMAL TEMP\n\t\t\t\t;PLUS 0.5 DEGREE IF C SET\n\treturn\n\nNEGATIVE\n\t;2'S COMPLIMENT NEGATIVE ROUTINE\n\nNOT_PRESENT\n\t;DS1820 NOT FOUND ROUTINE\n\nREAD_ERROR\n\t;READ ERROR ROUTINE\n\n\tGOTO\t$\t\t;TWIDDLE THUMBS.\n\nconvert\n\tmovf\tTEMP_LSB,w\n    movwf\tUNITS\n\tmovlw\t'0'\n       \n        movwf\tTENS\n\n\n\nDO10S\n\tmovlw\t.10\n\tsubwf\tUNITS,W\n\tbtfss\tSTATUS,C\n\tgoto\tADJUST\t\n\tmovwf\tUNITS\n\tincf\tTENS,F\n\tgoto\tDO10S\n\nADJUST\n\tmovlw\t'0'\n\taddwf\tUNITS,F\n\treturn\n\nSEGGY \n\n\t\tCALL GetBYTE\n        CALL SplitToTens\n        CALL DisplayDigits\n\n;===========================================================\n; Split number into tens and units\n;===========================================================\n; TEMP = input byte (0-99)\n; TENS = tens digit\n; UNITS = units digit\n\nGetBYTE\nmovfw TEMP_LSB\nmovwf LSB_Sanitise\nmovfw TEMP_MSB\nmovwf MSB_Sanitise\n\n\n\n; Inputs: byteA, byteB\n; Output: byteC\n\n; Step 1: Extract upper nibble of byteA to lower nibble\nSWAPF LSB_Sanitise, W\nANDLW 0x0F ;mask the first 4 bits, just need the last 4 after the nibble swap above\nMOVWF temp\n\n; Step 2: Extract lower nibble of byteB to upper nibble\n;movfw MSB_Sanitise, W\nSWAPF MSB_Sanitise, W\nANDLW 0x70 ;mask last 5 bits just need the first 3 after the nibble swap above\nMOVWF MSB_Sanitise\n\n\n; Step 3: Combine\nMOVFW MSB_Sanitise\nIORWF temp, W\nMOVWF CombinedByte ; combined the upper nibble ofr msb with the lower nibble\n;of lsb to get msb_lsb like this\n\n\nreturn\n\nSplitToTens\n;movlw b'00100001'\n;movwf CombinedByte ;--- Test if 33 works for instance during split\n\n; --- Start of conversion subroutine ---\nCONVERT_TEN_UNIT:\n    clrf        TENS_AGAIN      ; Initialize tens counter to zero\n    movf        CombinedByte, W   ; Load the number to convert into WREG\n    movwf       UNITS_AGAIN     ; Use UNITS_DIGIT as a temporary variable\n\nLOOP_SUBTRACT_TEN:\n    movlw       d'10'           ; Load 10 into WREG\n    subwf       UNITS_AGAIN, F  ; Subtract 10 from UNITS_DIGIT\n    btfss       STATUS, C       ; Skip the next instruction if C flag is set (no borrow)\n    goto        END_LOOP_SUBTRACT ; Jump if borrow occurred (result is negative)\n    incf        TENS_AGAIN, F   ; Increment the tens counter\n    goto        LOOP_SUBTRACT_TEN ; Repeat the subtraction\n\nEND_LOOP_SUBTRACT:\n    movlw       d'10'           ; Load 10 into WREG\n    addwf       UNITS_AGAIN, F  ; Add 10 back to restore the remainder\n    return                      ; Return from the subroutine\n; --- End of conversion subroutine ---\n\n\n;===========================================================\n; Display both digits (multiplex) USING TRANSISTOR AS A ---- HIGH SIDE SWITCH -----. ie when io pin is high, display is off. I think the display has potentially switched digits in the wiring compared to the old one\n;===========================================================\nDisplayDigits:\nmovlw 0x1E\nmovwf FILE1\n\nLOOPY1 movlw 0x03\nmovwf FILE2\n\nLOOPY2 movlw 0x03\nmovwf FILE3\n\nLOOPY3\n\n   ;---- Tens (left) ----\n        MOVF TENS_AGAIN,W\n        CALL DigitToSeg\n        MOVWF PORTB\n        BSF PORTA,2          ; enable tens (RA2)\n        BCF PORTA,1          ; disable units (RA1)\n        Call Delayswitch\n        ;BCF PORTA,2 old one to turn off tens\n\t\tBSF PORTA,1          ; turn off tens using new transistor\n\n\n        ;---- Units (right) ----\n        MOVF UNITS_AGAIN,W\n        CALL DigitToSeg\n        MOVWF PORTB\n        BSF PORTA,1          ; enable units (RA1)\n        BCF PORTA,2          ; disable tens (RA2)\n        Call Delayswitch\n        ;BCF PORTA,1          old one; turn off units\n\t\tBSF PORTA,2          ; turn off units using the transistor\n\ndecfsz FILE3, f\ngoto LOOPY3\n\ndecfsz FILE2, f\ngoto LOOPY2\n\ndecfsz FILE1, f\ngoto LOOPY1\n\n\n\n\n\t\ngoto carryon\n\n\nDelayswitch\tmovlw\td'10'\t\t\t;delay 250 ms (4 MHz clock)\n\tmovwf\tcount1\nd1\tmovlw\t0xC7\n\tmovwf\tcounta\n\tmovlw\t0x01\n\tmovwf\tcountb\nDelay_0\n\tdecfsz\tcounta, f\n\tgoto\t$+2\n\tdecfsz\tcountb, f\n\tgoto\tDelay_0\n\n\tdecfsz\tcount1\t,f\n\tgoto\td1\n\tretlw\t0x00\n\n\ncarryon\nRETURN\n\nEND\n\n<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>If you like, you can see the breadboard I used to prototype this for your reference:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5956-1024x768.jpg\" alt=\"\" class=\"wp-image-771\" srcset=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5956-1024x768.jpg 1024w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5956-300x225.jpg 300w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5956-768x576.jpg 768w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5956-1536x1152.jpg 1536w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5956.jpg 2000w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"1024\" src=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/image-768x1024.jpg\" alt=\"\" class=\"wp-image-772\" srcset=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/image-768x1024.jpg 768w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/image-225x300.jpg 225w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/image-1152x1536.jpg 1152w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/image.jpg 1500w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>And this was the original schematic I drew out first for your reference:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5965-1024x768.jpg\" alt=\"\" class=\"wp-image-776\" srcset=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5965-1024x768.jpg 1024w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5965-300x225.jpg 300w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5965-768x576.jpg 768w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5965-1536x1152.jpg 1536w, https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/img_5965.jpg 2000w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Now what you will need is the Gerber file to upload to JLCPCB. You may download it here:<\/p>\n\n\n\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-7c1119a4-7ea1-4d20-82da-3f5a5af3b417\" href=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/gerber.zip\">DOWNLOAD GERBER File here<\/a><a href=\"https:\/\/odonodesign.com\/blog\/wp-content\/uploads\/2026\/03\/gerber.zip\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-7c1119a4-7ea1-4d20-82da-3f5a5af3b417\">Download<\/a><\/div>\n\n\n\n<p>All you do is go to <a href=\"https:\/\/jlcpcb.com\">https:\/\/jlcpcb.com<\/a>, register for an account then hit &#8220;Order Now&#8221; at the top. Upload the Gerber file and leave all the other settings the same (i.e quantity 5, 2 layer, etc etc&#8230;) They will manufacture it for you and can send it to you within 10 days anywhere in the World for just \u00a33 for 5 PCB&#8217;s, that&#8217;s 5 TINY-Therms, Bargain! All you&#8217;ll need to do then is solder the components onto the board, attach the battery pack of 3AAA batteries, then fire it up!<br><br>Enjoy!<\/p>\n\n\n\n<p><strong>Disclaimer Notice:<\/strong> This is an educational tutorial only and I will not accept any responsibility for damage or harm to property and\/or persons as a result of you following and building this tutorial project. You are responsible for your own safety and performing any safety tests if used commercially. Ideally we recommend this for use only in personal\/hobby projects.<\/p>\n\n\n\n<p>This is an educational tutorial for personal use only. You must ensure you conduct the appropriate safety tests. But as an example, uses for this could include:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>Industrial systems, consumer products, systems which are sensitive thermally, thermostatic controls, and thermometers, monitor various environments and machinery, power plants, and manufacturing, weather stations and home automation systems, measure temperature in solids, liquids or gases, Laboratories, Diagnostic labs, Dairy Industries, Domestic or industrial refrigerator temperature monitoring, baby thermometer, HVAC, automotive, research and quality control, adult thermometer, room temperature monitoring, outside temperature logger, industrial and consumer goods\/products, wireless temperature monitor, LCD\/LED screen thermometer, temperature logger, farming, agriculture, office, home, manufactured goods, electronics engineering, embedded systems, integrated products, digital products, physical products, projects, end products, consumer goods, pcb design, printed circuit boards, plastic enclosures, remote temperature monitoring, motors, surface plates, home appliances, computers, industrial equipment, warning electrical radiators, exhaust gas monitoring on cars, food production, 3d printed chocolates, alcohol breathalyser, transit, hvac, power and utilities, calibration instrumentation, heat exchangers, heating cooling systems, energy, red sensor, etc thermistor, rtd sensors,<\/p>\n\n\n\n<p class=\"p1\">PIC16F628 assembly PIC assembly language tutorial PIC microcontroller vs Arduino PIC vs ESP32 DS18B20 PIC code 1-Wire protocol PIC PIC16F628 thermometer project PIC assembly firmware PIC microcontroller efficiency Why use PIC microcontrollers<\/p>\n\n\n\n<p class=\"p1\">cycle-accurate timing deterministic microcontroller code low-level embedded programming bare-metal programming PIC 1-Wire timing accuracy microcontroller power consumption interrupt-driven temperature reading embedded systems optimisation minimal instruction cycles lightweight firmware design<\/p>\n\n\n\n<p class=\"p1\">Arduino overhead Arduino timing limitations ESP32 FreeRTOS overhead Arduino digitalWrite speed ESP32 latency issues microcontroller bloatware embedded systems performance comparison<\/p>\n\n\n\n<p class=\"p1\">\u201cHow to read a DS18B20 temperature sensor using PIC assembly\u201d \u201cWhy PIC assembly is more efficient than Arduino\u201d \u201cPIC16F628 temperature sensor project with code\u201d \u201cBest microcontroller for simple temperature projects\u201d \u201cCycle accurate 1-Wire code for PIC microcontrollers\u201d \u201cHow to bit-bang 1-Wire in PIC assembly\u201d \u201cPIC16F628 DS18B20 wiring and schematic\u201d \u201cMinimalist microcontroller temperature monitor\u201d \u201cBare metal programming vs Arduino libraries\u201d \u201cWhy my Arduino DS18B20 readings are unstable\u201d \u201cOptimised DS18B20 firmware for 20 MHz PIC\u201d \u201cHow to create a reliable digital thermometer without Arduino\u201d \u201cUnderstanding PIC assembly timing for sensors\u201d<\/p>\n\n\n\n<p>Domestic Purpose, Check the temperature of the water before bathing, to check the temperature of food items for cooking, to measure the temperature of grill stands, ovens, and other heating appliances.<\/p>\n\n\n\n<p>Laboratory Purpose<\/p>\n\n\n\n<p>To check the temperature of a solution.<br>To check the room temperature or atmospheric temperature to carry out experiments.<\/p>\n\n\n\n<p>Industrial Purpose<\/p>\n\n\n\n<p>To measure the temperature of the inner and outer surfaces of the walls.<br>Food industries use them to monitor the temperature of food items during various stages of preparation. Especially in the baking and cooking industries, they are very useful. By taking the right temperature, it is possible to achieve the desired temperature where the microorganisms do not multiply.<\/p>\n\n\n\n<p>\u00a9 Copywrite ODONO DESIGN 2023<\/p>\n\n\n\n<p><strong>DISCLAIMER<\/strong><\/p>\n\n\n\n<p>This is an untested project. This is for hobby and personal use only. We do not allow commercial use of this tutorial (ie selling it in an end product, but if you are making this for commercial purposes, YOU are responsible for all CE, FCC and safety testing according to your jurisdiction. We will not be held responsible for any fire, damage or injury caused by this project.<\/p>\n\n\n\n<p><strong>COPYRIGHT AND TERMS OF USAGE (LISCENSE)<\/strong><\/p>\n\n\n\n<p>You are free to use this file for personal, hobby or educational purposes only. No commercial use of this project is permitted. None of the content on this webpage (code and hardware designs) may be plagiarised to other websites. Failure to comply will result in legal action. Thank you.<\/p>\n\n\n\n<p>This webpage is Copyright by Patrick O&#8217;Donoghue 2024. Temperature Monitor&nbsp;by Patrick O&#8217;Donoghue&nbsp;is licensed under&nbsp;<a href=\"https:\/\/creativecommons.org\/licenses\/by-nc-nd\/4.0\/?ref=chooser-v1\" target=\"_blank\" rel=\"noreferrer noopener\">CC BY-NC-ND 4.0&nbsp;<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello, the much loved Seven Segment Digital Thermometer has been improved upon! This is version 2.0 of TINY Therm. It basically improves its brightness and by driving the display directly from the power rails using 2 transistors. I\u2019ve also included a button so that it will stay asleep and only wake to show the temperature [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-773","post","type-post","status-publish","format-standard","hentry","category-tutorials"],"_links":{"self":[{"href":"https:\/\/odonodesign.com\/blog\/wp-json\/wp\/v2\/posts\/773","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/odonodesign.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/odonodesign.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/odonodesign.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/odonodesign.com\/blog\/wp-json\/wp\/v2\/comments?post=773"}],"version-history":[{"count":12,"href":"https:\/\/odonodesign.com\/blog\/wp-json\/wp\/v2\/posts\/773\/revisions"}],"predecessor-version":[{"id":796,"href":"https:\/\/odonodesign.com\/blog\/wp-json\/wp\/v2\/posts\/773\/revisions\/796"}],"wp:attachment":[{"href":"https:\/\/odonodesign.com\/blog\/wp-json\/wp\/v2\/media?parent=773"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/odonodesign.com\/blog\/wp-json\/wp\/v2\/categories?post=773"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/odonodesign.com\/blog\/wp-json\/wp\/v2\/tags?post=773"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}