Featured

Ambient Light Controller Software

Ambient Light Controller Software

Please read Liability Disclaimer and License Agreement CAREFULLY

This piece of software is running on the Ambient Light Controller described in Ambient light with APA102 and MQTT

The main features are:

- Read the voltage, curent and power information provided by INA260 using I2C protocol and timers

- Get the color data from Ambient Light Sensor Controller's and send gain value using USART

- Send and receive data to/from ESP8266 attached to this board (MQTT topics values) using USART

- Send data to APA102 RGB LED strips concted on SPI

- All USART receive are done using DMA to minimize the load on the MCU

In main.c I use timeToRead as a fix time period reminder to read the data from INA260, timeToSend  is used to send the energy consumption data to ESP8266. 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{
	if(htim->Instance==TIM2) {
		timeToRead = 1;
	} else if(htim->Instance==TIM3){
		timeToSend = 1;
  }
}

The main algorithm logic is:

- If the MQTT power is set to Off, then we turn Off the LED strips

- If MQTT power topic is On, then if we are in MQTT Sensor mode we check if we got data from Ambient Light Sensor Controller and then we send the data to APA102 LED Strips

- If we are not in Sensor mode we are in automatic effects or we get the color directly from OpenHAB, in both situation we push the color data to LED strips

- If is time to read the INA260 data, we read it and we store it in a buffer.

- If is time to send the INA260 data, we use USART3 in DMA mode to send the buffer to ESP8266

- If we have new data from ESP8266 we check to see if we have updates for brightness vale and gain. If new values are available we update the old ones and forward the new values.

  while (1)
  {
		//The Power state has changed
		if(prevPower != frame_MQTT[Power]){
			prevPower = frame_MQTT[Power];
			//The power is OFF
			if(!prevPower){
				APA_AllOff();
				//Stop DMAs to save power?
			}
		}
		if(prevPower){
				//If Power is ON
				// We are in sensor mode
				if(frame_MQTT[Mode]){
					//We have data from left/Right side sensor
					//0, 1, 2 Top Sensor - near debug interface
					//6, 7, 8 Bottom Sensor - near case wall
						if(LC_Ready){
							//tL = HAL_GetTick() - tL1;
							for(cnt = 0; cnt < FirstThird; cnt++){
								APA_setColor(cnt, rxL[0], rxL[1], rxL[2]);
								APA_setColor(cnt + FirstThird, rxL[3], rxL[4], rxL[5]);
								APA_setColor(cnt + SecondThird, rxL[6], rxL[7], rxL[8]);
							}
							APA_update(0);
							LC_Ready = 0;
							//tL1 = HAL_GetTick();
						}
						if(RC_Ready){
						//tr = HAL_GetTick() - tR1;
							for(cnt = 0; cnt < FirstThird; cnt++){
								APA_setColor(cnt, rxR[0], rxR[1], rxR[2]);
								APA_setColor(cnt + FirstThird, rxR[3], rxR[4], rxR[5]);
								APA_setColor(cnt + SecondThird, rxR[6], rxR[7], rxR[8]);
							}
							APA_update(1);
							RC_Ready = 0;
							//tR1 = HAL_GetTick();
						}
				} else {
					// Run lights effects
					if(frame_MQTT[Effect]){
						//If an effect was completed
						if(effectDone){
							//We start a new one
							effectDone = 0;
							switch(frame_MQTT[Effect]){
								case 1:
									FluidRainbowCycle(effectDuration);
								break;
								case 2: 
									SnowEffect(50);
								break;
								case 3: 
									PulseEffect(effectDuration);
								break;
								case 4: 
									FlashingEffect(effectDuration);
								break;
								case 5: 
									FadingEffect(effectDuration);
								break;
								case 6: 
									ColorWipe(effectDuration);
								break;
								case 7: 
									TheaterChase(frame_MQTT[LeftRed], frame_MQTT[LeftGreen], frame_MQTT[LeftBlue], effectDuration);
								break;
								case 8: 
									BreathEffect(effectDuration);
								break; 
								case 9: 
									WaveEffect(effectDuration);
								break; 
							}				
						}
					} 
				}
			}
		// We have data from ESP (MQTT)
		UpdateAPA();
		
		//End of APA stuff / Begin of INA260
		
		// Read INA260 power values
		if(timeToRead){
			if(ina260_conversion_ready()){
				ina260_get_voltage(&measures[0]);
				ina260_get_current(&measures[1]);
				ina260_get_power(&measures[2]);
				//Transform Power to Energy
				measures[3] += measures[2] * sHour;
				timeToRead = 0;
			}
		}
		//Send energy measurements to ESP to be displayed in OpenHab
		//Send the values every 30s to avoid loading Zigbee network
		if(timeToSend){
			//4x floats = 16bytes
			memcpy(valToSend+1, measures, 16);
			HAL_UART_Transmit_DMA(&huart3, (uint8_t *)&valToSend, txLen);
			timeToSend = 0;
		}
  }

The full code can be downloaded here.

Comments powered by CComment