Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Capturing serial data using PIC24

Status
Not open for further replies.

nick2412

New Member
Hi all,

I’m using a PIC24FJ128GA010 (16-bit) MCU to program numerous sensors for a smart heating system, using C programming. I have only one sensor left to program and it’s an infra-red thermometer sensor (the TN-901 by Zytemp). The problem with this sensor is that it sends two types of messages – ambient room temperature and object temperature. I only need the latter, and the data is transferred via a single data pin continuously. However, this data transfer is dependent on another clock pin that comes FROM the sensor, and the clock frequency of 2 KHz. Data bits can be read at every falling edge of the clock (see timing diagram - not drawn to scale **broken link removed** ). The two types of messages can be distinguished by the first byte, known as the header. Each message in total is 5 bytes – 1 byte for the header, 2 bytes for the temperature, 1 byte for the SUM and 1 byte for the Carriage Return (40 bits in total). I just want to capture the object temperature whose header byte is 4C (HEX), and use it for further calculations.

I have tried to use SPI, setting the sensor as a slave, and capturing the data from the SPI buffer, but that has not been successful. Also, from my understanding, the data flow is based on a clock from the master which I tried setting the sensor as, but again, not successful. And, as with traditional SPI, something needs to be written first in order to read data, but this sensor does not require any data to be written to it. One of the pins (the ‘Action’ pin) just needs to be grounded for the data to be sent continuously.

I was told to try generating an interrupt at every falling edge of the clock frequency, capture the bit from the data pin, put it in a variable and logic-shift the variable to the left (and keep doing this for 40 bits). I am using two variables for this, one being 32-bit (of type long) and one being 16-bit (of type int) as I cannot put the whole 40 bits into one variable (long long is still 32 bits as I found out by monitoring the register values). This method kinda works, except that it takes a really long time (about 80-90 seconds to see something on the LCD the first time, and every 30-40 seconds to refresh) and the values don’t seem to be accurate. I’m assuming the delay is probably due to the fact that my interrupt is probably too long and that it’s generated throughout run-time (as the data flow is continuous with short delays between messages). Is there any way to speed this up? I’m assuming the inaccuracy is probably due to the lack of synchronization of the message (the bits are probably being captured somewhere at the middle of the message). I’ve attached my code below.

I also tried turning on the sensor when I needed to capture the data, and then turn off the sensor when I didn’t need it. However, this also didn’t work because, as I noticed from an oscilloscope, the data flow went all haywire since it was being powered on and off in such a short period of time.

At this point, I’m only displaying the header on the LCD, as I know that the following 2 bytes will be the temperature value, so if I capture at least the header, I’ll know I’m on the right track. Can anyone please offer any suggestions/improvements for my code or any alternate method of capturing this data? Please advise asap. Thanks in advance.

Code:
unsigned long ShiftVal_1 = 0;
unsigned int ShiftVal_2 = 0;
unsigned int header;
int bit_count = 0, INT2_flag = 0;

void __attribute__((__interrupt__)) _INT2Interrupt(void) {
	bit_count++;
	if (bit_count <= 32) {
		ShiftVal_1 |= PORTDbits.RD14; //ORing data with new bit
		ShiftVal_1 = ShiftVal_1 << 1; //Logic-shift left
	}
	else if (bit_count > 32 && bit_count <= 40) {
		ShiftVal_2 |= PORTDbits.RD14;
		ShiftVal_2 = ShiftVal_1 << 1;
	}
	else
		INT2_flag = 1;
	
	IFS1bits.INT2IF = 0; // Clearing interrupt flag
}

int main (void) {
	
	unsigned int INT2Config;
	
	//Configure I/O pins as input
	TRISDbits.TRISD14 = 1; // Data on RD14
	TRISEbits.TRISE9 = 1; // Clock on RE9/INT2
	
	//Configure interrupt on RE9 on falling edge
INT2Config = FALLING_EDGE_INT | EXT_INT_PRI_1 | EXT_INT_ENABLE;
	ConfigINT2(INT2Config);
	
	.
	.
	.

	while (1) {

		.
		.
		.

                while(!INT2_flag); // Wait until 40 bits captured
		INT2_flag = 0;
	
		// Filter header value
		header = (unsigned int)(ShiftVal_1>>24);
			
		// Display header value on LCD
ShortToString((int)header,4,back_str+ADC_POS_NUMBER);
	
                         bit_count = 0;
		ShiftVal_1 = 0;
		ShiftVal_2 = 0;

        }
}
 
Shouldn't you shift the value and then or in the bit. The way it is at the moment, 0x4C would come out as 0x98. Is this what you are seeing?

Mike.
 
I was told to try detecting the delay between the 40 bit messages (which is roughly 100ms), then wait until the first bit comes out, and then start to read the next 39 bits. Can anyone tell me how this can be done based on the clock frequency of the sensor?
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top