Skip to the content.

Appendix E: MQTT Topic Table and C code

MQTT Topic Table

Table EA: MQTT Topic Table

C project code

/* PROJECT: PRO_FullCode.X
* EGR314 6PM Team 305 Microcontroller Code for Weather Station Project
* Mark Alvarez, Tristan Dunton, Kevin Hays, Aaron Karsten
* Professor: Travis Kelley
* Main author: Kevin Hays
* Supporting authors: Tristan Dunton, Mark Alvarez, Aaron Karsten
* Last Rev. 04/23/2023
*/
  
/*                                                                         TODO:
* Ask Kelley about Timestamps over MQTT-----------------------------------------Call to something? Server maybe?
* Ask Kelley how to push to different topics with ESP---------------------------Change variable in async mqtt.py
* Ask Kelley how to check if the data was sent----------------------------------Unknown
*/

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/examples/i2c2_master_example.h"
#include "mcc_generated_files/i2c2_master.h"
#include "stdio.h"
#include <stdint.h>
#include <stdbool.h>
#include <xc.h>
#include <stdlib.h>
  
//Check if sensors and motor are readable
int CheckSystem(void){
    //Initialize variables
    uint8_t tempCheck, lightCheck, errorCode;
	char motorData[100];

	//Reads anything from the sensors to make sure they're connected
	tempCheck = I2C2_Read1ByteRegister(0x4C, 0x00);
	lightCheck = I2C2_Read1ByteRegister(0x39, 0x5A);
	
	//Reads anything from the motor to make sure it's connected
	CSN1_SetLow();
	__delay_ms(10);
	motorData[0] = 0b11001101;
	SPI1_ExchangeBlock(motorData, 1);
	__delay_ms(100);
	CSN1_SetHigh();
	
	//Returns errors if nothing was read!
	if (tempCheck == 0){
	    printf("Error Code 8!");
	    errorCode = errorCode + 8;
	}
	if (lightCheck == 0){
	    printf("Error Code 9!");
	    errorCode = errorCode + 9;
	}
	if (motorData[0] != 0b11001101){
	    printf("Error Code 7!");
	    errorCode = errorCode + 7;
	}
	switch(errorCode){
	    case 7:
	        printf("Error Code 7!");
	        break;
	    case 8:
	        printf("Error Code 8!");
	        break;   
	    case 9:
	        printf("Error Code 9!");
	        break;   
	    case 15:
	        printf("Error Codes 7 & 8!");
	        break; 
	    case 16:
   		        printf("Error Codes 7 & 9!");
    	    break; 
    	case 17:
    	    printf("Error Codes 8 & 9!");
    	    break; 
    	case 24:
    	    printf("Error Codes 7, 8, & 9!");
    	    break; 
	}
	
	return errorCode;
}		

void Enable_LS(void){
	I2C2_Write1ByteRegister(0x39,0x80, 0b00011011);   //enable device function       
}

//Runs the motor forward (Steps 1 & 3)
void MotorForward(void){
    char data[100];
    
    CSN1_SetHigh();
    SPI1_Open(SPI1_DEFAULT);
    //Forward
        CSN1_SetLow();
        __delay_ms(10);
        data[0]=0b11111111;
        SPI1_ExchangeBlock(data, 1);
        __delay_ms(1000);
        CSN1_SetHigh();
    //printf("Forward!\r");
    
    //Stop
        CSN1_SetLow();
        __delay_ms(10);
        data[0]=0b11101101;
        SPI1_ExchangeBlock(data, 1);
        __delay_ms(1000);
        CSN1_SetHigh();
    //printf("STOP!!\r");
}

//Runs the Motor Backwards (Step 2)
void MotorReverse(void){
    char data[100];

    //Reverse
    for(int i; i < 20; i++){
        CSN1_SetLow();
        __delay_ms(10);
        data[0]=0b1111110;
        SPI1_ExchangeBlock(data, 1);
        __delay_ms(100);
        CSN1_SetHigh();
    }
    //printf("Reverse!!!\r");
    //__delay_ms(1000);
    
    //Stop
    for(int i; i < 10; i++){
        CSN1_SetLow();
        __delay_ms(10);
        data[0]=0b11101101;
        SPI1_ExchangeBlock(data, 1);
        __delay_ms(100);
        CSN1_SetHigh();
    }
    //printf("STOP!!!!!!\r");
    //__delay_ms(1000);
}

//PID Error checker
int ErrorCheck(uint8_t tAvg){
    uint8_t tOrigin = I2C2_Read1ByteRegister(0x4C, 0x00);
    uint8_t pidError = 0, t0 = 0, t1 = 0;
    //Calculates the error. If it's greater than 2 degrees C, Run a test again.
    if(abs(tOrigin - tAvg) > 2){
        //Motor goes forward
        MotorForward();
                
        //Reads the sensors
        t0 = I2C2_Read1ByteRegister(0x4C, 0x00);
                
        //Motor goes backwards
        MotorReverse();
                
        //Reads the sensor
        t1 = I2C2_Read1ByteRegister(0x4C, 0x00);
                
        //Motor goes forwards to the origin
        MotorForward();
                
        //Averages the temperatures
        tAvg = ((t0 + t1) / 2);
        pidError = abs(tOrigin - tAvg);
        printf("Recorded Temperature: %d; Temperature Error: %d; ", tAvg, pidError);
    }
    else{
        printf("Recorded Temperature: %d; ", tAvg);
    }
    return pidError;
}

void EUSART2Transmit(void){
    EUSART2_Receive_ISR();
    
    volatile uint8_t unifData;
    
    if(EUSART2_is_rx_ready()){
        unifData = EUSART2_Read();
        if(EUSART3_is_tx_ready()){
            EUSART3_Write(unifData);
        }
        if(EUSART3_is_tx_done()){ 
        }
        //LED_0_Toggle();
    }
}

void EUSART3Transmit(void){
    EUSART3_Receive_ISR();
    
    volatile uint8_t unixData;
    
    if(EUSART3_is_rx_ready()){
        unixData = EUSART3_Read();
        if(EUSART2_is_tx_ready()){
            EUSART2_Write(unixData);
        }
        if(EUSART2_is_tx_done()){
        }
    }
}

//Main Loop
void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();
    EUSART2_SetRxInterruptHandler(EUSART2Transmit);
    EUSART3_SetRxInterruptHandler(EUSART3Transmit);
    Enable_LS();
    
    // Enable Interrupts
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();
 
    //Initialize variables
    uint8_t t0, t1, tAvg, lightData[2], lightBytes[2];
    uint16_t L0, L1, LAvg;
   		int runTimer = 0;
	int runTimeTotal = 0;
	int errorCode = 0;
	int pidError = 0;
	int systemOK = 1;
	float timeBuffer;
	uint8_t ii = 0;
	while (systemOK == 1){
    	t0 = I2C2_Read1ByteRegister(0x4C, 0x00);
    	lightBytes[0] = I2C2_Read1ByteRegister(0x39, 0x95);  // data low bytes
    	lightBytes[1] = I2C2_Read1ByteRegister(0x39, 0x96); //data high bytes
    	lightData[0] = I2C2_Read1ByteRegister(0x39, 0xAD);  // data low bytes, low light 
    	lightData[1] = I2C2_Read1ByteRegister(0x39, 0xAE);  // data high bytes, high light level
    	L0 = lightData[0] << 8 | lightData[1];
    	ii++;
    	printf("ii: %d; Temp: %d; Light %u; \r", ii, t0, L0);
    	__delay_ms(1000);
    	if(runTimer == 0){
        	errorCode = CheckSystem();
        	if(errorCode == 0){
            	//Motor goes forward
            	MotorForward();
            
            	//Reads the sensors
            	t0 = I2C2_Read1ByteRegister(0x4C, 0x00);
            	lightBytes[0] = I2C2_Read1ByteRegister(0x39, 0x95);  // data low bytes
            	lightBytes[1] = I2C2_Read1ByteRegister(0x39, 0x96); //data high bytes
            	lightData[0] = I2C2_Read1ByteRegister(0x39, 0xAD);  // data low bytes, low light 
            	lightData[1] = I2C2_Read1ByteRegister(0x39, 0xAE);  // data high bytes, high light level
            	L0 = lightData[0] << 8 | lightData[1];
            	
            	//Motor goes backwards
            	MotorReverse();
            	
            	//Reads the sensors
            	t1 = I2C2_Read1ByteRegister(0x4C, 0x00);
            	lightBytes[0] = I2C2_Read1ByteRegister(0x39, 0x95);  // data low bytes
            	lightBytes[1] = I2C2_Read1ByteRegister(0x39, 0x96); //data high bytes
            	lightData[0] = I2C2_Read1ByteRegister(0x39, 0xAD);  // data low bytes, low light 
            	lightData[1] = I2C2_Read1ByteRegister(0x39, 0xAE);  // data high bytes, high light level
            	L1 = lightData[0] << 8 | lightData[1];
            	
            	//Motor goes forwards to the origin
            	MotorForward();
            	
            	//Averages the temperatures and light
            	tAvg = ((t0 + t1) / 2);
            	LAvg = ((L0 + L1) / 2);
            	
            	//Checks the error for the temperature. If it's too high, run the tests for temperature again to confirm
            	pidError = ErrorCheck(tAvg);
            	
            	printf("Light Sensed: %d nm; \r", LAvg);
        	}	
        	else{
        	    systemOK = 0;
        	}
        	runTimer++;
        	runTimeTotal = runTimeTotal + runTimer;
        	timeBuffer = runTimeTotal / 10.0;
        	printf("Total Run Time: %f s.\r", timeBuffer);
    	}
    	else if(runTimer >= 18000){
        	runTimer = 0;
    	}
    	else{
        	runTimer++;
    	}
    	__delay_ms(100);
	}
  	}

/**
 	End of File
*/

For the full project, as well as the python code for the ESP32, please refer to Team305’s code repo here.

click here to return to index