NEWBIE Needs Help on PIC12F683 and Proteus 8 Pro - Page 1
Forum section: electronics / beginners

author: emredemircio
author_rank: Contributor
timestamp: December 13, 2023, 04:10:16 pm
content: Hello passengers!I have a PIC12F683, an IRFZ44N MOSFET, a green and a red LED, a DHT11 temperature sensor, and a heating element(20 ohm). I would like to build a temperature control system. The sensor will get temperature data and if the temperature is lower than 35 celsius, heating will start and if the temperature is above 40 celsius, heating will stop. I want PIC12F683 to read temperature data from DHT11 and trigger the gate of the MOSFET IRFZ44N with the conditions I mentioned above. IDE is MPLAB X and I use Proteus 8 Pro for simulation. This is my code:I compiled the code both on MPLAB IDE X and Proteus 8 Professional, with no errors. Also proteus simulation works with no errors. I know no errors do not mean it is gonna function as I wish but... After getting errors for days, it is a thing.And I am a rookie on Proteus.For now, I didn't add LEDs both in the code and Proteus, I also attach my Proteus file.Code:/** File: test.c*/#include <xc.h>#include <pic12f683.h>// PIC12F683 Configuration Bit Settings// 'C' source line config statements// CONFIG#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)#pragma config BOREN = ON // Brown Out Detect (BOR enabled)#pragma config IESO = ON // Internal External Switchover bit (Internal External Switchover mode is enabled)#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)// #pragma config statements should precede project file includes.// Use project enums instead of #define for ON and OFF.#define _XTAL_FREQ 4000000 // Assuming 4MHz oscillator frequency#define DHT11_PIN GP0 // Pin connected to DHT11 sensor#define LED_GREEN GP1 // Green LED pin#define LED_RED GP2 // Red LED pin#define HEATING_ELEMENT GP5 // Pin connected to heating element#define TEMP_LOWER_LIMIT 35#define TEMP_UPPER_LIMIT 40// Function prototypesvoid dht11_start();uint8_t dht11_read();void readDHT11(uint8_t *temp, uint8_t *hum);void controlHeating(uint8_t temperature);void main(void) {uint8_t temperature, humidity;TRISIO = 0x01; // Set GP0 as input (Temperature Sensor Data), others as outputGPIO = 0x00; // All output pins low initiallywhile (1) {readDHT11(&temperature, &humidity);controlHeating(temperature);// Implement LED control logic here based on temperature if needed}}void dht11_start() {TRISIO &= ~(1 << DHT11_PIN); // Set DHT11_PIN as outputGPIO &= ~(1 << DHT11_PIN); // Pull the data line low__delay_ms(18); // Hold the line low for at least 18msGPIO |= (1 << DHT11_PIN); // Release the line__delay_us(30); // Wait for DHT11 responseTRISIO |= (1 << DHT11_PIN); // Set DHT11_PIN as input to read sensor response}uint8_t dht11_read() {uint8_t data = 0;for (int i = 0; i < 8; i++) {while (!(GPIO & (1 << DHT11_PIN))); // Wait for the data line to go high (start of data)__delay_us(30); // Wait for 30us to ensure it's a valid bitif (!(GPIO & (1 << DHT11_PIN))) {// If the line is still low after waiting, it's a '0' bitdata <<= 1; // Shift left by 1 bit} else {// If the line is high, it's a '1' bitdata |= 0x01; // OR operation with 0x01data <<= 1; // Shift left by 1 bitwhile (GPIO & (1 << DHT11_PIN)); // Wait for the line to go low (end of data)}}return data;}void readDHT11(uint8_t *temp, uint8_t *hum) {dht11_start(); // Initialize communicationif (!(GPIO & (1 << DHT11_PIN))) {__delay_us(80);if (GPIO & (1 << DHT11_PIN)) {__delay_us(80);*hum = dht11_read(); // Read humidity*temp = dht11_read(); // Read temperatureuint8_t checksum = dht11_read(); // Read checksumif (checksum != (*hum + *temp)) {// Checksum doesn't match data// Handle error or retry reading}}}}void controlHeating(uint8_t temperature) {if (temperature < TEMP_LOWER_LIMIT) {// Turn on heating elementGPIO |= (1 << HEATING_ELEMENT);} else if (temperature > TEMP_UPPER_LIMIT) {// Turn off heating elementGPIO &= ~(1 << HEATING_ELEMENT);}}

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 13, 2023, 10:43:39 pm
content: For 683 and FT, try again to RTFMRequired initialization of '683 peripherals, etc is missing in main()Your read routine of humtemp module is NFG and inconsistent with its datasheet.While your while() is just doing doo doo, you would do anyone helping a favor to tell what exactly you C it do do.Otherwise, its fine.

author: emredemircio
author_rank: Contributor
timestamp: December 13, 2023, 11:59:10 pm
content: Oh thanks for the help but I understood, uhm... nothing

author: Kim Christensen
author_rank: Super Contributor
timestamp: December 14, 2023, 12:00:25 am
content: Quote from: emredemircio on December 13, 2023, 04:10:16 pmYou need a logic level MOSFET for that. A IRFZ44N will not reliably turn on with only 5V on the gate. Some might work. Others may not when it's cold or when the moon is in the 7th house.

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 14, 2023, 04:17:33 am
content: Be careful, you must await for Jupiter to align with Mars!RTFM: A big turn-on, but you must wait for a while(). If you read verse 4 of the sensor DHT specsheet you will see you must wait.N n e case,If you read DHT verse 5 you might see that your read routine might apply to receiving data from Uranus but its no way reading data from your DHT.But you never tell what you get when you power up.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 14, 2023, 05:09:58 am
content: Quote from: SuzyC on December 13, 2023, 10:43:39 pmBut he's not using any peripherals, just gpio, so seems fine.

author: emredemircio
author_rank: Contributor
timestamp: December 14, 2023, 05:19:39 am
content: I read the manual but had no idea how to add delay... Now I added a delay of 1000 ms, could you please check?Code:/** File: test.c* Author: Administrator** Created on 13 Aral?k 2023 Çar?amba, 12:52*/#include <xc.h>#include <pic12f683.h>#include <stdint.h>// PIC12F683 Configuration Bit Settings// 'C' source line config statements// CONFIG#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)#pragma config BOREN = ON // Brown Out Detect (BOR enabled)#pragma config IESO = ON // Internal External Switchover bit (Internal External Switchover mode is enabled)#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)// #pragma config statements should precede project file includes.// Use project enums instead of #define for ON and OFF.#define _XTAL_FREQ 4000000 // Assuming 4MHz oscillator frequency#define DHT11_PIN GP0 // Pin connected to DHT11 sensor#define LED_GREEN GP1 // Green LED pin#define LED_RED GP2 // Red LED pin#define HEATING_ELEMENT GP5 // Pin connected to heating element#define TEMP_LOWER_LIMIT 35#define TEMP_UPPER_LIMIT 40// Function prototypesvoid StartSignal();uint8_t dht11_read();void readDHT11();uint8_t data, temp, hum;void StartSignal() {__delay_ms(1000);TRISIO = 0x00; // Set DHT11_PIN as outputGP0 = 0; // Pull the data line low__delay_ms(18); // Hold the line low for at least 18msGP0 = 1; // Release the line__delay_us(30); // Wait for DHT11 responseTRISIO = 0x01; // Set DHT11_PIN as input to read sensor response}uint8_t dht11_read() {uint8_t data = 0;for (int i = 0; i < 8; i++) {while (!(GPIO & (1 << DHT11_PIN))); // Wait for the data line to go high (start of data)__delay_us(30); // Wait for 30us to ensure it's a valid bitif (!(GPIO & (1 << DHT11_PIN))) {// If the line is still low after waiting, it's a '0' bitdata <<= 1; // Shift left by 1 bit} else {// If the line is high, it's a '1' bitdata |= 0x01; // OR operation with 0x01data <<= 1; // Shift left by 1 bitwhile (GPIO & (1 << DHT11_PIN)); // Wait for the line to go low (end of data)}}return data;}void readDHT11() {StartSignal(); // Initialize communicationif (!(GPIO & (1 << DHT11_PIN))) {__delay_us(40);if (GPIO & (1 << DHT11_PIN)) {__delay_us(80);hum = dht11_read(); // Read humiditytemp = dht11_read(); // Read temperatureuint8_t checksum = dht11_read(); // Read checksumif (checksum != (hum + temp)) {// Checksum doesn't match data// Handle error or retry reading}}}}void main(uint8_t temp) {TRISIO = 0;GP5 = 1;while(1) {StartSignal();readDHT11();if(data == 1){temp = dht11_read();}if (temp < 35) {// Turn on heating elementGP5 = 1;} else if (temp > 40) {// Turn off heating elementGP5 = 0;}}}

author: Ian.M
author_rank: Super Contributor
timestamp: December 14, 2023, 06:33:46 am
content: Quote from: DavidAlfa on December 14, 2023, 05:09:58 amNot so. All analog capable pins default to analog mode on powerup/reset, so read as 0 in the GPIO SFR irrespective of their level. Additionally the O.P's doing Read-Modify-Write operations on GPIO to bitbang individual output pins, which will clear any other output pins in analog mode.RMW on ports is problematic enough, even if you don't guarantee failure by lack of initialisation . . .SeeRMW and solutions for it @Microchip forum

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 14, 2023, 08:40:27 am
content: Yo!Got I/O?Code to read hum and temp,Are not what specsheet said!You can waitasec,Or wait 4 ever,Read ur way,Will work never!

author: Ian.M
author_rank: Super Contributor
timestamp: December 14, 2023, 09:04:56 am
content: Even if the code was to spec, its still not going to read anything from the GP0/AN0 pin while that is in analog mode!

author: emredemircio
author_rank: Contributor
timestamp: December 14, 2023, 09:58:18 am
content: Code:void DHT11_Start(void) {__delay_ms(1000);ANSEL = 0; // Dijital olarak kullanilacakCMCON0 = 7;TRISIO &= ~(1 << DHT_PIN);GPIO &= ~(1 << DHT_PIN);__delay_ms(25);GPIO |= (1 << DHT_PIN);__delay_us(30);TRISIO |= (1 << DHT_PIN);Will that do? ANSEL = 0 and CMCON0 =7.

author: Ian.M
author_rank: Super Contributor
timestamp: December 14, 2023, 10:47:18 am
content: Those SFRs, set to those values is correct for putting all pins in digital mode, but its illogical to put it in DHT11_Start() as it affects pins other than GP0/AN0. Either put those statements at the top of the code in main() or create an init function for them + all other GPIO initialisation.

author: emredemircio
author_rank: Contributor
timestamp: December 14, 2023, 11:01:00 am
content: Okay now I am removing those from that function.

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 14, 2023, 11:02:53 am
content: You can test your I/O even without a scope. You can light a LED on another I/O and the LED on the other pin shows the state of the I/O pin reading the DHTCan you light a LED on another pin for 1-sec on..1-sec off on? ?Another I/O pin can then show the state (on/off) of the GP0 pin.Can you show the state of your DHT I/O pin with a LED on another I/O pin? (without any flicker)If all I/O works well then correct your read DHT code RTFM-----------------------------You don't have to get too fancy when codingreading or writing on the DHT I/O pin.ANSEL only needs to be stated once in your main() code.You can then TRIS the GP0 just once and then it stays in the digital as input or output state until you need to change the I/O pin from input output or input again.TRIS, & and bit shifting need notcomplicate, need not be part of a read pin state or write pin state to achieve I/O operation.KISSTo wit,if GP0 is set as digital out I/O pin by TRIS, then you can simply write a one by "GP0=1;"You can then read(determine the state of) if GPO is TRIS'd. as a digital inputThen you can simply read its state byif(GP0==1) then{ //your code}Is your code "if (!(GPIO & (1 << DHT11_PIN))) { //easy to read??

author: emredemircio
author_rank: Contributor
timestamp: December 14, 2023, 11:07:06 am
content: Come on man I am so new on this. I read the manual more than 10 times, reading it whenever I get confused. I am trying to figure out things...

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 14, 2023, 11:45:38 am
content: RTFM once again.Hint: The verse 5 clearly states thatthe width of a "1" bit outputby the DHT determines if thedata bitis a one or zero.1 and 0's are different in pulse width. A zero bit level is not used to indicate a 1 or zero bit is being output.But your code so far seems to think otherwise.Einstein once told Feynman that "If you cannot explain what you know to someone else in simple terms, then you don't understand what you are doing."If you don't understand works the same way.When you encounter something you don't understand, post that troubling sentence and what you think it means to get help. Not mentioning anything is not a way to get help, will get you slowly nowhere.

author: emredemircio
author_rank: Contributor
timestamp: December 14, 2023, 03:12:02 pm
content: OoookayI learned that after 50 us, 26-28 us high means0and 70 us high means1. I know that. Einstein reference did not help me. I also know how to read. I dont know how to code it. If you wanna lecture me so bad, I am ready to learn how to program this small thing. That is all I am saying. Again, thank you for your time.About TRIS... I would like to communicate with DHT11 on a single pin. When initializing, shoulnd't I TRIS it first to 0 to send data and set it back TRIS 1 to receive data? Or can I set TRIS once as digital and make t input or output by typing GP0 = 1 or GP0 = 0?I am a bit confused. Datasheet chapter 4 states that TRISIO sets pins as input or output. CMCON0 and ANSEL registers must be initialized to make pins digital.Code:ANSEL = 0;CMCON0 = 0x07;is that right or ... ?

author: Ian.M
author_rank: Super Contributor
timestamp: December 14, 2023, 04:33:45 pm
content: Lets look at datasheet section 4 example 1Code:BANKSEL GPIO ;CLRF GPIO ;Init GPIOMOVLW 07h ;Set GP<2:0> toMOVWF CMCON0 ;digital I/OBANKSEL ANSEL ;CLRF ANSEL ;digital I/OMOVLW 0Ch ;Set GP<3:2> as inputsMOVWF TRISIO ;and set GP<5:4,1:0>;as outputsand how it translates to C.There are a couple of things you need to know:In the (obsolete) MPASM assembly language,;starts a (single line) comment. In C use//In MPASM, a trailinghon a number indicates its in hexadecimal. In C, use a leading0x. i.e. 07h becomes 0x07.XC8 manages bank and page selection automatically for you so you can discard anypageselorbankseldirective lineSome SFR names are slightly different in C vs MPASM assembler, and vs the datasheet. If it fails to compile with an error indicating a problem with a SFR name, check the device specific header file for the correct name to use.So that whole example translated to a snippet of XC8 C, preserving comments, is:Code:GPIO=0; //Init GPIOCMCON0=0x07; //Set GP<2:0> to digital I/OANSEL=0; //digital I/OTRISIO=0x0C; //Set GP<3:2> as inputs//and set GP<5:4,1:0> as outputsIts in the datasheet, its the official sequence to initialise the GPIO port, it isn't voided by any known errata, so yes, use it. Obviously, change the TRISIO line and ANSEL line for whatever mix of digital inputs and outputs and analog inputs you actually need. The XC8 language extension of0bas a prefix for binary numbers is useful here as you can do:Code:TRISIO=0b001100;which is exactly equivalent to setting it to 0x0C but shows the I/O state of each pin more obviously.There's another trap for young players - newer PICS have a separate ANSELx SFR for each port with analog capable pins and the bits in it are in the same order as the PORTx or TRISx bits, with unimplemented bits for digital only pins, so its easy to understand what mode each pin is in. Your PIC and a lot of other older PICs pack it into one ANSEL SFR (or two with an ANSELH), by not having bits for digital only pins, so the bit positions in TRIS and ANSEL don't all match up. Your PIC confuses it further by packing the A/D Conversion Clock Select bits in the high nibble of ANSEL.

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 14, 2023, 04:41:23 pm
content: Just take the task step by step and you'll get there in time.If a pin is set to be an input it can be either analog or digital. ANSEL sets a TRIS'd to 1 pin as a digital input pin to be an A2D (analog) input.So don't do that.ANSEl=0 just once sets all I/O pins to digital I/0 and for then on it stays as only a digital input or output.RTFM the Microchip '683 spec sheet carefully. It has a clearly written section on IO ports which explains all this. Only a few things to learn. All PIC MCU's have a few paragraphs about this to show configuration of I/O pins.RTFM. Code to create the sequence of operations described in the DHT specsheet!You need to first set (TRIS't to 0) the pin to be adigital output to output a couple of bits that request the DHT to send data to you..TRIS'it to 0 and send the timed few bits to the DHT.You then set(TRIS the pin to 1) the same I/O pin as a digital input to receive data from the DHT.You must follow the timing!Its just a script. Remember that when the bits from the DHT change state, you must read or start a timed delay.Your job is to try to understand this info: You can configure pins as digital inp or out and learn how to read and write with the same pin.The DHT specsheet shows the complete bit stream handshake to communicate. Read it carefully and experiment. If you have scope, you've got it made.1) First, configure a pin as output and output the carefully timed bit sequence to the DHT that tells it you want it to send data to you.2) Then immediately reconfig this pin as an inp and detect the start bits and then read the 40 data bits into your '683 one by one.3) Bingo, you get 40 bits in a stream of bits that tells you temp and humidity and a checksum as bonus!.When bits change from 1 to 0's and back to 1 again, you measure the pulse width of the '1' bit sent to determine if its 1 or 0 bit of data.The critical thing is always timing. Use delays to lead up to any read or write any bit..just follow the DHT data stream bit sequence.Surf the data stream!When you read it enough, try to explain the operation to yourself by drawing a bit stream diagram like you were explaining it to someone else. If your description then matches what the datasheet says, you're ready to do get the data you want from the DHT.You're almost there..only a few bits more to success!

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 14, 2023, 05:06:10 pm
content: Hint:You can measure the pulse width ofevery single inputted 1 or 0bit interval in an input data stream byperiodically polling(reading the state)of your digital I/O input pin every for a so and so number of mSec or uSecs delays in a loop. Sum your delays. When the bit changes state you then read the sum of your delays to read the summed bit width of your polling intervals. This technique tells you how long the bit has been a 1 or a 0. You add the sum of the delays between the start and finish of a bit level, whether it is a 1 or 0, the timed sum is the bit width, the sum of your delays between level changes.Once you got the width measured correctly you can easily follow your bit position in the data stream to know what to do next!Ok, the above is abitrepetitious, but I want you to get the point!

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 14, 2023, 11:45:45 pm
content: ANSEL and CMCON0 registers must be configured to set the pins as digital:QuoteQuoteThus, ANSEL=0, CMCON0 = 7.The DHT11 sequence and timing are wrong, you're shifting the bit 8 times (Skip last bit), also missing the fractional bytes (Checksum computation will be always bad...) all wrong LOL.Also, you must provide a pullup resistor to the data pin, can be external or internal (Through WPU register).Apart frorm that, the whole thing is overcomplicated, can be done much simpler.Proteus is a bit buggy, after writting 0 to GPIO always reads 0 in input mode. Setting it to 1 in input mode seems to work.4MHz (1us CPU cycle) is very tight in processing power, better run it at 8MHz, also open project settings, compiler options, and set optimization level to 2 (Available for free) or s (Optimize for size, only in Pro mode).It might fail if not enabling any optimization!Read this!https://mcuoneclipse.com/2015/03/27/using-the-dht11-temperaturehumidity-sensor-with-a-frdm-board/Now please read this, understand what it does and learn about it, instead just copy & pasting.Code:#include <xc.h>#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)#pragma config BOREN = ON // Brown Out Detect (BOR enabled)#pragma config IESO = ON // Internal External Switchover bit (Internal External Switchover mode is enabled)#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)#define DHT11_PIN GP0#define DHT11_TRIS TRISIO0#define DHT11_WPU WPU0#define HEATER_PIN GP5#define LED_GREEN GP1#define LED_RED GP2#define pin_input 1#define pin_output 0#define enable 1#define disable 0#define _XTAL_FREQ 8000000UL // 8MHz oscillator frequency#define TEMP_LOWER_LIMIT 35#define TEMP_UPPER_LIMIT 40void dht11_start();uint8_t dht11_read();void readDHT11(uint8_t *temp, uint8_t *hum);void controlHeating(uint8_t temperature);void main(void) {uint8_t temperature, humidity;#if (_XTAL_FREQ == 8000000UL)OSCCON |= 0b01110001; // IRCF = 111 (8MHz), internal clock#endifCMCON0 = 7; // All comparator pins as digitalANSEL = 0; // All ADC pins as digitalTRISIO = 0; // All pins as outputDHT11_TRIS = pin_input; // Except DHT11 pinnGPPU = 0; // Global pullup enable bitDHT11_WPU = 1; // Enable DHT11 pin pull-up__delay_ms(500); // Initial delay at power-on to let everything settle downwhile (1) {readDHT11(&temperature, &humidity);controlHeating(temperature);__delay_ms(1000); // Wait 1s for next cycle (DHT11 cycle is 1Hz)}}void dht11_start() {DHT11_PIN = disable;DHT11_TRIS = pin_output;__delay_ms(20); // Hold the line low for at least 18msDHT11_PIN = enable;DHT11_TRIS = pin_input;__delay_us(10); // Wait 10us to prevent noise (Expected 30us)while(DHT11_PIN); // Wait until pin goes low__delay_us(10); // Wait 10us to prevent noise (Expected 80us)while(!DHT11_PIN); // Wait until pin goes high}uint8_t dht11_read() {uint8_t data = 0;for (uint8_t i = 0; i < 8; i++) { // Receive 8 bitsdata <<=1; // Shift datawhile(DHT11_PIN); // Wait until pin goes low (start of data)__delay_us(5); // Wait 5us to prevent noisewhile(!DHT11_PIN); // Wait until pin goes high (data)__delay_us(30); // Wait 30us (1=70us, 0=26us)data |= DHT11_PIN; // Store bit}return data;}void readDHT11(uint8_t *temp, uint8_t *hum) {uint8_t data, checksum = 0;dht11_start(); // Initialize communicationfor (uint8_t i = 0; i < 5; i++) { // Read data. Compute checksum later.data = dht11_read();}for (uint8_t i = 0; i < 4; i++) { // Compute checksumchecksum += data;}if (checksum != data) { // Compare checksum*hum = 255; // Error*temp = 255;}else { // Copy data*hum = data;*temp = data;}}void controlHeating(uint8_t temperature) {if (temperature < TEMP_LOWER_LIMIT) {HEATER_PIN = enable;} else if (temperature > TEMP_UPPER_LIMIT) {HEATER_PIN = disable;}}

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 15, 2023, 02:24:28 am
content: Alternatively, you might consider purchase of anANALOG only output sensor,no digital datastream to handshake and get values, just pure DC voltages for both temp and humidity. You simply use 2 (very simple to code) A2D inputs on your MCU to read the temp and hum output values.Mouser also stocks models with I2C interface, but that's another digital, but possibly simpler programming challenge for a noobie.Very inexpensive, greater accuracy, rugged, small size, greater measurement ranges, in stock!Mouser No:403-SHT40I-HD1B-R2Mfr. No:SHT40I-HD1B-R2

author: emredemircio
author_rank: Contributor
timestamp: December 16, 2023, 01:49:33 pm
content: This is MASTERCLASS!!! OMG!!!I am a bit shocked. Straight to the solution. I can't appreciate you ever enough. I am gonna analyze this to the last bit. Great help! I wasnt expecting this to be honest!!!

author: emredemircio
author_rank: Contributor
timestamp: December 16, 2023, 06:09:15 pm
content: I am also working on an analog temperature sensor because this DHT11 is max 50 celsius. Maybe useful for reading weather temperature but not enough for some higher temperature jobs.In fact, I am planning to do lots of projects to have more insight about those MCUs.

author: emredemircio
author_rank: Contributor
timestamp: December 16, 2023, 06:46:57 pm
content: I would like to ask some question to have a better grasp...1.__delay_ms(500); // Initial delay at power-on to let everything settle downAs you say this an extra delay to settle and prevent power on peaks. I know it is too short of a time but have to ask if this is seriously necessary? Do we have any malfunctions if we remove this line of code?(just curiosity)2a. When we makeTRISIO0 = 0;this puts the pin onoutputmode, what happens if we makeGP0 = 1;andGP0 = 0;? (Also when TRISIO0=1;) I am probably gonna need a correction probably.- TRISIO0= 0;- GP0=0means the pin is on output mode but it is not sending anything(low mode, 0V) andGP0 = 1means it is now sending (5V, high).2b. -- TRISIO0= 1 ;- GP0=0means the pin is on input mode and its voltage is 0V(low) andGP0 = 1meansI COULD NOT FIGURE THIS OUT LOL. Maybe this means it is now at 5V and receiving data...3.Code:uint8_t dht11_read() {uint8_t data = 0;for (uint8_t i = 0; i < 8; i++) { // Receive 8 bitsdata <<=1; // Shift datawhile(DHT11_PIN); // Wait until pin goes low (start of data)__delay_us(5); // Wait 5us to prevent noisewhile(!DHT11_PIN); // Wait until pin goes high (data)__delay_us(30); // Wait 30us (1=70us, 0=26us)data |= DHT11_PIN; // Store bit}return data;}In this snippet;- Why do we shift bits? What does shifting bit means? (I googled it but still...)-__delay_us(30); // Wait 30us (1=70us, 0=26us)I am a bit confused. Manuals says every bit of daha begins with a 50 us low-voltage-level and if +70= 1 and +26=0. Why do we wait only for 30 us? what about 50us at the beginning of the bit? I could not get this.Also any suggestions on a quality source for learning C for PIC is much much appreciated. Thank you!

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 16, 2023, 08:40:13 pm
content: __delay_ms(500);Specsheet says in Section 4, must wait 1-second on power up before interacting with this device. This is too short.-------------------------------------------------------------------------------With the DHT11. you are only working with digital signals, so setting ANSEL=0 keeps every pin used in a digital logic level read or write mode.Once you TRIS a pin = 0, the pin is in the output mode and stays in the output mode until changed by you or a reset occurs.Once you TRIS GPO pin =0 then you can output to an external device on that pin.If the pin is GPO, thenGP0=1; //sets this output pin to a logical high '1' level,GP0=0; //sets this pin to a logical low '0' level.//-----------If you TRIS a pin = 1 with ANSEL=0; //then the pin is in a digital input mode and can read only a 1 or 0 on the output level of any external device pin this pin is connected to.If the pin is connected to a logical one hi-level voltage, (DHT pin=1)the MCU would read/see the '1' digital logical level as being input.//so you might codeuint8_t DHT_OutputSignalState; //Var to be used to read/examine/store the digital bit state when reading the GPO pin and//then if GPO is connected to the DHT pin (and you have a pullup resistor to Vdd. This is as shown in your posted schematic)DHT_OutputSignalState=GPO; //when GPO is in the digital input mode.However, after TRiS'd =1 to be in digitalinputmode this same pin can be switched to be an analog input pin using ANSEL. in this mode, instead of reading a digital input/output level, the MCU's A2D peripheral set correctly can read any voltage level this pin is connected to externally.You do this by setting this same set to digital input by TRIS=1 pin to an analog input mode by setting ANSEL reg pin = 1;

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 16, 2023, 08:58:34 pm
content: - TRISIO0= 1 ;- GP0=0 means the pin is on input mode and its voltage is 0V(low) and GP0 = 1 means I COULD NOT FIGURE THIS OUT LOL. Maybe this means it is now at 5V and receiving data.=========When you use TRIS a pin to 1, the pin is in a digital input mode, so trying to output (GP0=1;)makes no senseyou don't output on a pin when it is in the input mode.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 16, 2023, 09:03:39 pm
content: Quote from: SuzyC on December 16, 2023, 08:40:13 pmProbably, I never used a DHT11, I just focused on the timings.QuoteTRISIO0=0 puts GP0 in output mode. Writing to GP0 will set the output state.TRISIO0=1 puts GP0 in input mode. Writing to GP0 makes no effect. Reading GP0 reflects the state of the pin.However, I explained why I'm setting GP0 high/low, due a Proteus bug.Quote from: DavidAlfa on December 14, 2023, 11:45:45 pmQuoteShifting is the same as rotating:Data = 01000010Data <<=1;Data = 10000100QuoteIt already waited for the data going low and rising again, that's the part detecting each data bit.After 30us the data will be 0 again (Next start) if it was a "0” bit (26us), or still 1 for a "1" bit (70us).Code:uint8_t dht11_read() {uint8_t data = 0;for (uint8_t i = 0; i < 8; i++) { // Receive 8 bitsdata <<=1; // Shift datawhile(DHT11_PIN); // Wait until pin goes low (start of data)__delay_us(5); // Wait 5us to prevent noisewhile(!DHT11_PIN); // Wait until pin goes high (data)__delay_us(30); // Wait 30us (1=70us, 0=26us) <-----data |= DHT11_PIN; // Store bit}return data;}The shift is placed first because we don't want to rotate the last bit.At first data=0 so it makes no effect

author: SuzyC
author_rank: Frequent Contributor
timestamp: December 16, 2023, 09:15:09 pm
content: In this snippet;- Why do we shift bits?What does shifting bit means? (I googled it but still...)The hum and temp are serially sent out from the DHT in bit order, highest bit first.It makes sense to send the highest bit first and yet put the bit received into the rightmost bit position of the receiving data byte.Shifting the value read left then allows the next lower bit to be placed in the rightmost bit positionof the data word being read.After the last bit is input, all the bits have then marched(shifted left) into their correct data position.Each shift marches all the bits in the receiving word left one position. After 8 shifts, all bits are in their correct position.

author: Ian.M
author_rank: Super Contributor
timestamp: December 16, 2023, 09:17:00 pm
content: Technically, writing to a port pin that's in input mode *DOES* have an effect but it is hidden until the pin is next made an output.Look at the datasheet FIGURE 4-2: BLOCK DIAGRAM OF GP1If you write to the port while any of its pins are in input mode, you preload the output latches for those pins with whatever you write, without affecting the external pin. The latched level then takes effect immediately when you change the pins mode to output, but has no effect until then. This behaviour is commonly used, presetting the output latch low, to fake an open drain I/O pin, output controlled by its TRIS bit, e.g. when bit-banging I2C.As usual on the older PICs, the RMW effect must be carefully considered as the output latches aren't accessible for readback while in input mode.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 16, 2023, 09:39:58 pm
content: Let's pulse a led when reading the data, so you can visually see how it's doing:Code:uint8_t dht11_read() {uint8_t data = 0;for (uint8_t i = 0; i < 8; i++) { // Receive 8 bitsdata <<=1; // Shift datawhile(DHT11_PIN); // Wait until pin goes low (start of data)__delay_us(5); // Wait 5us to prevent noisewhile(!DHT11_PIN); // Wait until pin goes high (data)__delay_us(30); // Wait 30us (1=70us, 0=26us)data |= DHT11_PIN; // Store bitLED_GREEN=1;LED_GREEN=0; // Small LED pulse}return data;}Remember:Quote from: DavidAlfa on December 16, 2023, 09:03:39 pmLet's suppose this byte:This is how the shifting/rotation works:Quote