|
|
View previous topic :: View next topic |
Author |
Message |
woser
Joined: 24 Feb 2011 Posts: 8
|
DS18b20 PIC16F84A and 4x7-segment LED problem |
Posted: Thu Feb 24, 2011 7:45 am |
|
|
Hello, trying to write a program to the old thermometer. And I have no idea to get it to work. The display is working properly now only has a problem with the DS18B20 is connected to the port of A4. Below is my code.
Schematic :
Code: |
#include <16f84a.h>
#USE DELAY( CLOCK=4000000 ) /* Using a 4 Mhz clock */
#FUSES XT,NOWDT,NOPROTECT,NOPUT
/* Use XT mode, No Watch Dog, No Code Protect, No Power-up Timer */
#byte port_b=6 /* define the location of register port_b */
#byte port_a=5 /* define the location of register port_b */
byte CONST LED_MAP[12] = {0x24,0xe7,0x4c,0x45,0x87,0x15,0x14,0x67,0x04,0x05,0xfb,0xdf};
byte CONST LED_POZ[4] = {0x04,0x02,0x01,0x08};
unsigned int mask(unsigned int num);
unsigned int minus, ulamek, cyfra, dziesiatka;
int8 i;
signed int16 temperature;
int8 scratch[9];
#define DQ PIN_A4
//-------------------------------------
void ow_reset(void)
{
output_low(DQ);
delay_us(500); // Min. 480uS
output_float(DQ);
delay_us(500); // Wait for end of timeslot
}
//-------------------------------------
// Read bit on one wire bus
int8 read_bit(void)
{
output_low(DQ);
delay_us(1);
output_float(DQ);
delay_us(12); // Read within 15uS from start of time slot
return(input(DQ));
}
//-------------------------------------
int8 read_byte(void)
{
int8 i;
int8 val = 0;
for(i=0 ; i<8 ; i++)
{
if(read_bit()) val |= (0x01 << i);
delay_us(120); // To finish time slot
}
return val;
}
//-------------------------------------
void write_byte(int8 val, int8 power_on)
{
int i;
for(i=0; i<8; i++)
{
output_low(DQ);
delay_us( 2 );
output_bit(DQ, shift_right(&val,1,0));
delay_us(60);
if((i == 7) && (power_on == 1))
{
output_high(DQ);
}
else
{
output_float(DQ);
delay_us( 2 );
}
}
}
void wyswietl_xy(int poz, int cyfra)
{
port_a=LED_POZ[poz];
port_b=LED_MAP[cyfra];
}
main(){
disable_interrupts ( GLOBAL );
setup_timer_0 ( RTCC_DIV_1 | RTCC_INTERNAL );
set_timer0 (0);
enable_interrupts ( GLOBAL );
enable_interrupts (INT_RTCC);
set_tris_b(0); /* set port_b as outputs */
set_tris_a(0); /* set port_a as output */
port_b = 0; /* ZERO port_a & port_b */
port_a = 0;
output_float(DQ);
while(1)
{
ow_reset();
write_byte(0xCC, 0); // Skip Rom command
write_byte(0x44, 1); // Temperature Convert command
delay_ms(750); // Max. time for conversion is 750mS
ow_reset();
write_byte(0xCC, 0); // Skip Rom command
write_byte(0xBE, 0); // Read scratch pad command
// Get the data bytes
for(i=0; i < 8; i++)
{
scratch[i] = read_byte();
}
ow_reset();
temperature = (signed int16) make16(scratch[1],scratch[0]);
if(temperature >= 0)
temperature = (temperature + 8)/16;
else
temperature = (temperature - 8)/16;
cyfra=temperature;
}
}
#INT_RTCC
TIMER_INTERRUPT ( )
{
if(minus==1) {wyswietl_xy(3,11);}
delay_us(330);
if(dziesiatka!=0) {wyswietl_xy(2,dziesiatka);}
delay_us(330);
wyswietl_xy(1,cyfra);
delay_us(330);
wyswietl_xy(1,10);
delay_us(330);
wyswietl_xy(0,ulamek);
delay_us(330);
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9247 Location: Greensville,Ontario
|
|
Posted: Thu Feb 24, 2011 8:08 am |
|
|
Is this real hardware or a Proteus project ?
Proteus is full of 'bugs' but you can see and touch hardware!
Divide and conquer !
Since you say the display is working, I'd write new code, just to test the DS chip.
Basically read the DS chip and send the result to a PC using RS232.That way you can be sure the timings for the DS chip are correct.
The pullup should be 4K7 on the DQ pin.
Once that works, 'merege' the two working programs into a third.
Be sure to save backups of working code ! |
|
|
woser
Joined: 24 Feb 2011 Posts: 8
|
|
Posted: Thu Feb 24, 2011 8:58 am |
|
|
Yes it's real project and it's works with old software but the software has a bug so I decide to write my own and the display work fine but I can't retrive information from ds probably it is a stupid mistake. This is my first program for the PIC , I always write for atmega
is it ok for my schematic ?
Code: |
#byte port_b=6 /* define the location of register port_b */
#byte port_a=5 /* define the location of register port_b */
#define DQ PIN_A4
|
And it ?
Code: |
disable_interrupts ( GLOBAL );
setup_timer_0 ( RTCC_DIV_1 | RTCC_INTERNAL );
set_timer0 (0);
enable_interrupts ( GLOBAL );
enable_interrupts (INT_RTCC);
set_tris_b(0); /* set port_b as outputs */
set_tris_a(0); /* set port_a as output */
port_b = 0; /* ZERO port_a & port_b */
port_a = 0;
|
|
|
|
woser
Joined: 24 Feb 2011 Posts: 8
|
|
Posted: Thu Feb 24, 2011 10:55 am |
|
|
I found probably a bug in comparison with the original software on the 5V line RA4 in my program that is not: (. How does it solve? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
woser
Joined: 24 Feb 2011 Posts: 8
|
|
Posted: Fri Feb 25, 2011 1:53 am |
|
|
Ok ds18b20 now is working but I have problem again with multiplexing, can anybody help how to set ok delays between segments in the timer ?
Code: |
#include <16f84a.h>
#USE DELAY( CLOCK=4000000 ) /* Using a 4 Mhz clock */
#FUSES XT,NOWDT,NOPROTECT,NOPUT
/* Use XT mode, No Watch Dog, No Code Protect, No Power-up Timer */
#byte port_b=6 /* define the location of register port_b */
#byte port_a=5 /* define the location of register port_b */
byte CONST LED_MAP[12] = {0x24,0xe7,0x4c,0x45,0x87,0x15,0x14,0x67,0x04,0x05,0xfb,0xdf};
byte CONST LED_POZ[4] = {0x04,0x02,0x01,0x08};
unsigned int minus, ulamek, cyfra, dziesiatka;
/*
* One wire (1-wire) driver for CCS C compiler. Suitable for use with devices
* such as the DS18B20 1-wire digital temperature sensor.
*/
float value = 0.0;
float temp;
#define ONE_WIRE_PIN PIN_A4
/*
* onewire_reset()
* Description: Initiates the one wire bus.
*/
// OK if just using a single permanently connected device
void onewire_reset() {
output_low(ONE_WIRE_PIN); // pull the bus low for reset
delay_us(500);
output_float(ONE_WIRE_PIN); // float the bus high
delay_us(500); // wait-out remaining initialisation window
output_float(ONE_WIRE_PIN);
}
/*
* onewire_write(int8 data)
* Arguments: a byte of data.
* Description: writes a byte of data to the device.
*/
void onewire_write(int8 data) {
int8 count;
for(count = 0; count < 8; ++count) {
output_low(ONE_WIRE_PIN);
delay_us(2); // pull 1-wire low to initiate write time-slot.
output_bit(ONE_WIRE_PIN, shift_right(&data, 1, 0)); // set output bit on 1-wire
delay_us(60); // wait until end of write slot.
output_float(ONE_WIRE_PIN); // set 1-wire high again,
delay_us(2); // for more than 1us minimum.
}
}
/*
* onewire_read()
* Description: reads and returns a byte of data from the device.
*/
int onewire_read() {
int count, data;
for(count = 0; count < 8; ++count) {
output_low(ONE_WIRE_PIN);
delay_us(2); // pull 1-wire low to initiate read time-slot.
output_float(ONE_WIRE_PIN); // now let 1-wire float high,
delay_us(8); // let device state stabilise,
shift_right(&data, 1, input(ONE_WIRE_PIN)); // and load result.
delay_us(120); // wait until end of read slot.
}
return data;
}
/*
* ds1820_read()
* Description: reads the ds18x20 device on the 1-wire bus and returns
* the temperature
*/
float ds1820_read() {
int8 busy=0, temp1, temp2;
signed int16 temp3;
float result;
//ds1820_configure(0x00, 0x00, 0x00); //9 bit resolution
onewire_reset();
onewire_write(0xCC); //Skip ROM, address all devices
onewire_write(0x44); //Start temperature conversion
while(busy == 0) //Wait while busy (bus is low)
busy = onewire_read();
onewire_reset();
onewire_write(0xCC); //Skip ROM, address all devices
onewire_write(0xBE); //Read scratchpad
temp1 = onewire_read();
temp2 = onewire_read();
temp3 = make16(temp2, temp1);
//result = (float) temp3 / 2.0; //Calculation for DS18S20 with 0.5 deg C resolution
result = (float) temp3 / 16.0; //Calculation for DS18B20
delay_ms(200);
return(result);
}
/*
* ds1820_configure(int8 TH, int8 LH, int8 config)
* Description: writes configuration data to the DS18x20 device
* Arguments: alarm trigger high, alarm trigger low, configuration
*/
void ds1820_configure(int8 TH, int8 TL, int8 config) {
onewire_reset();
onewire_write(0xCC); //Skip ROM, address all devices
onewire_write(0x4E); //Write to scratchpad
onewire_write(TH);
onewire_write(TL);
onewire_write(config);
}
void wyswietl_xy(int poz, int cyfra)
{
port_a=LED_POZ[poz];
port_b=LED_MAP[cyfra];
}
main(){
setup_timer_0 ( RTCC_DIV_256 | RTCC_INTERNAL );
set_timer0 (0);
enable_interrupts (GLOBAL );
enable_interrupts (INT_RTCC);
set_tris_b(0); /* set port_b as outputs */
set_tris_a(0); /* set port_a as output */
port_b = 0; /* ZERO port_a & port_b */
port_a = 0;
while(1)
{
value = ds1820_read();
if(value<0)
{
minus=0;
value=value*-1;
}
else minus=1;
cyfra= (int)value%10;
dziesiatka=(int)value/10;
//temp=value-(int)value;
// delay_ms(100);
}
}
#INT_RTCC
TIMER_INTERRUPT ( )
{
if(minus!=1) {wyswietl_xy(3,11);}
delay_us(2640);
if(dziesiatka!=0) {wyswietl_xy(2,dziesiatka);}
delay_us(2640);
wyswietl_xy(1,cyfra);
delay_us(2640);
wyswietl_xy(1,10);
delay_us(2640);
wyswietl_xy(0,ulamek);
delay_us(2640);
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9247 Location: Greensville,Ontario
|
|
Posted: Fri Feb 25, 2011 6:57 am |
|
|
In your original post you said the display was OK...
I suggest you eliminate the Dallas code and used a fixed reading, say -12.3, to test your code for the display. This way you know what it should be and can figure it out.
Your code for the display is not in English ,makes hard for me to tell what is going on, but I can't see how it could work
Also I don't see where variable 'ulamek' has data put in. |
|
|
woser
Joined: 24 Feb 2011 Posts: 8
|
|
Posted: Fri Feb 25, 2011 7:54 am |
|
|
Code: | #INT_RTCC
TIMER_INTERRUPT ( )
{
if(minus!=1) {show_xy(3,11);}
delay_us(2640);
if(hundred!=0) {show_xy(2,tens);}
delay_us(2640);
show_xy(1,number);
delay_us(2640);
show_xy(1,10);
delay_us(2640);
show_xy(0,less_than_one);
delay_us(2640);
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9247 Location: Greensville,Ontario
|
|
Posted: Fri Feb 25, 2011 8:38 am |
|
|
you'll have to show the whole program, as you've made changes including variables that we can't see as well as a new function show_xy... |
|
|
woser
Joined: 24 Feb 2011 Posts: 8
|
|
Posted: Fri Feb 25, 2011 9:21 am |
|
|
Code: |
#include <16f84a.h>
#USE DELAY( CLOCK=4000000 ) /* Using a 4 Mhz clock */
#FUSES XT,NOWDT,NOPROTECT,NOPUT
/* Use XT mode, No Watch Dog, No Code Protect, No Power-up Timer */
#byte port_b=6 /* define the location of register port_b */
#byte port_a=5 /* define the location of register port_b */
byte CONST LED_MAP[12] = {0x24,0xe7,0x4c,0x45,0x87,0x15,0x14,0x67,0x04,0x05,0xfb,0xdf};
byte CONST LED_POSITION[4] = {0x04,0x02,0x01,0x08};
unsigned int minus, less_than_one, single_number, tens;
/*
* One wire (1-wire) driver for CCS C compiler. Suitable for use with devices
* such as the DS18B20 1-wire digital temperature sensor.
*/
float value = 0.0;
float temp;
#define ONE_WIRE_PIN PIN_A4
/*
* onewire_reset()
* Description: Initiates the one wire bus.
*/
// OK if just using a single permanently connected device
void onewire_reset() {
output_low(ONE_WIRE_PIN); // pull the bus low for reset
delay_us(500);
output_float(ONE_WIRE_PIN); // float the bus high
delay_us(500); // wait-out remaining initialisation window
output_float(ONE_WIRE_PIN);
}
/*
* onewire_write(int8 data)
* Arguments: a byte of data.
* Description: writes a byte of data to the device.
*/
void onewire_write(int8 data) {
int8 count;
for(count = 0; count < 8; ++count) {
output_low(ONE_WIRE_PIN);
delay_us(2); // pull 1-wire low to initiate write time-slot.
output_bit(ONE_WIRE_PIN, shift_right(&data, 1, 0)); // set output bit on 1-wire
delay_us(60); // wait until end of write slot.
output_float(ONE_WIRE_PIN); // set 1-wire high again,
delay_us(2); // for more than 1us minimum.
}
}
/*
* onewire_read()
* Description: reads and returns a byte of data from the device.
*/
int onewire_read() {
int count, data;
for(count = 0; count < 8; ++count) {
output_low(ONE_WIRE_PIN);
delay_us(2); // pull 1-wire low to initiate read time-slot.
output_float(ONE_WIRE_PIN); // now let 1-wire float high,
delay_us(8); // let device state stabilise,
shift_right(&data, 1, input(ONE_WIRE_PIN)); // and load result.
delay_us(120); // wait until end of read slot.
}
return data;
}
/*
* ds1820_read()
* Description: reads the ds18x20 device on the 1-wire bus and returns
* the temperature
*/
float ds1820_read() {
int8 busy=0, temp1, temp2;
signed int16 temp3;
float result;
//ds1820_configure(0x00, 0x00, 0x00); //9 bit resolution
onewire_reset();
onewire_write(0xCC); //Skip ROM, address all devices
onewire_write(0x44); //Start temperature conversion
while(busy == 0) //Wait while busy (bus is low)
busy = onewire_read();
onewire_reset();
onewire_write(0xCC); //Skip ROM, address all devices
onewire_write(0xBE); //Read scratchpad
temp1 = onewire_read();
temp2 = onewire_read();
temp3 = make16(temp2, temp1);
//result = (float) temp3 / 2.0; //Calculation for DS18S20 with 0.5 deg C resolution
result = (float) temp3 / 16.0; //Calculation for DS18B20
delay_ms(200);
return(result);
}
/*
* ds1820_configure(int8 TH, int8 LH, int8 config)
* Description: writes configuration data to the DS18x20 device
* Arguments: alarm trigger high, alarm trigger low, configuration
*/
void ds1820_configure(int8 TH, int8 TL, int8 config) {
onewire_reset();
onewire_write(0xCC); //Skip ROM, address all devices
onewire_write(0x4E); //Write to scratchpad
onewire_write(TH);
onewire_write(TL);
onewire_write(config);
}
void show_xy(int position, int single_number)
{
port_a=LED_POSITION[position];
port_b=LED_MAP[single_number];
}
main(){
setup_timer_0 ( RTCC_DIV_256 | RTCC_INTERNAL );
set_timer0 (0);
enable_interrupts (GLOBAL );
enable_interrupts (INT_RTCC);
set_tris_b(0); /* set port_b as outputs */
set_tris_a(0); /* set port_a as output */
port_b = 0; /* ZERO port_a & port_b */
port_a = 0;
while(1)
{
value = ds1820_read();
if(value<0)
{
minus=0;
value=value*-1;
}
else minus=1;
single_number= (int)value%10;
tens=(int)value/10;
//temp=value-(int)value;
// delay_ms(100);
}
}
#INT_RTCC
TIMER_INTERRUPT ( )
{
if(minus!=1) {show_xy(3,11);}
delay_us(2640);
if(tens!=0) {show_xy(2,tens);}
delay_us(2640);
show_xy(1,single_number);
delay_us(2640);
show_xy(1,10);
delay_us(2640);
show_xy(0,less_than_one);
delay_us(2640);
}
|
|
|
|
woser
Joined: 24 Feb 2011 Posts: 8
|
|
Posted: Fri Feb 25, 2011 12:45 pm |
|
|
The principle is very simple, the main loop reads DS18B20 and enter the number of different global variables, and the timer global variables are displayed. The problem is only when the timer accordingly to multiplex the digits on the display |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9247 Location: Greensville,Ontario
|
|
Posted: Fri Feb 25, 2011 1:48 pm |
|
|
Have you created a program that just cycle through the numbers 0 to 9, at say the 'ones digit' to confirm your decode table is correct?
The port pin to display segment isn't 'nice', ie: it isn't B.0 = a,B.1=b,etc.
Makes it very difficult to see if it is correct for the common anode display I assume you're using.
Depending on the multiplex rate,you'll need to increase the current to the display but go too far and the PIC may blowup.
You can of course for test purposes not use the timer interrupt and just run the code in 'main'
Be sure to disable all interrupts first though.
I'd still 'force' the value to be displayed to say -123 for test purposes, as you could have incorrect wiring but think it's a code problem. |
|
|
woser
Joined: 24 Feb 2011 Posts: 8
|
|
Posted: Fri Feb 25, 2011 3:25 pm |
|
|
I don't know why when I change DIV_256 to another DS18b20 doesn't work ?? |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|