Android app for remote control

 

This app can be used together with Arduino, ESP8266, Raspberry pi and many other modules where you require to send/receive data via WiFi.  By pressing an on or off button on the main screen the app will send the data specified in the settings tab to your module. Your Arduino, ESP8266, Raspberry pi can use this data to enable or disable any device like (home) lamps, televisions, modems, camera’s etc.

In the settings tab you can set up a destination IP address and port number to send data after you pressed a button on the main screen. In the settings tab you can predefine the transmitting data corrosponding to a button. After pressing the button the predefined data will be send to your module and can be handled there to activate led’s, lamps, televisions, fan’s or anything your project requires.

If the module sends the same data back to this app the app will detect this and change the status on the mainscreen. This is to make sure your module has a way to confirm the required action is done completely by the module.

The Android remote buttons app can be downloaded here.

The Atmega328 code

The software is a simplefied version of the software in my last blog. The last software “web server” was a bit more complicated, because a browser sends around 500 byters on average and thats a lot for this microcontroller. The Android app only sends around 50 bytes, depending what text you predefine. In the last blog I tried to keep the buffer small and therefor I had to programm some bufferoverflow corrections and thats not needed for this project. Besides that, a web page had to be send by the microcontroller to the web browser and that also takes a lot of bytes. With the Android app we only have to send about 50 bytes, again depending on the predefined text.

The working is simple. The ESP8266 waits for an incoming TCP/IP message send by the Android app. The ESP8266 passes this message to the microcontroller. The microcontroller checks if the incoming message match with some predefined values. If not it discarge the message. If it matches a led will be triggered and a message will appear on the lcd. After that the received message will be send back to the ESP8862 via the UART and the ESP8266 will convert it to TCP/IP and sends it back to the Android app. This whole loop just continues for ever. Download the full code for the microcontroller here and see the main changes compared to the framework below.

Application1.c

/*
 * application1.c
 *
 * Created: 8-2-2018 15:07:22
 * Author: HdH
 * Description: webserver controlling 4 outputs.
 */

#define F_CPU 16000000UL // 16 MHz clock speed for delay.h
#define PIN_LED1 10
#define PIN_LED2 9
#define PIN_LED3 6
#define PIN_LED4 8

#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "gpiolib.h"
#include "i2cdisplay.h"
#include "esp8266.h"



/****************************************************************************
	Bit and byte definitions
****************************************************************************/


extern int alarmCode;


void Application1(void){

uint8_t p;

	p = readInComing(0, NULL); // Checking incoming uart data
	switch (p){
	
		case BTN1RCVDON:
			writeI2cDisplayLine("Button1 on pressed",0,1);
			writePin(PIN_LED1, HIGH);
			esp8266_send(BTN1ONTEXT);
			resetIncoming();
			break;
		case BTN1RCVDOFF:
			writeI2cDisplayLine("Button1 off pressed",0,1);
			writePin(PIN_LED1, LOW);
			esp8266_send(BTN1OFFTEXT);
			resetIncoming();
			break;
		case BTN2RCVDON:
			writeI2cDisplayLine("Button2 on pressed",0,1);
			writePin(PIN_LED2, HIGH);
			esp8266_send(BTN2ONTEXT);
			resetIncoming();
			break;
		case BTN2RCVDOFF:
			writeI2cDisplayLine("Button2 off pressed",0,1);
			writePin(PIN_LED2, LOW);
			esp8266_send(BTN2OFFTEXT);
			resetIncoming();
			break;
		case BTN3RCVDON:
			writeI2cDisplayLine("Button3 on pressed",0,1);
			writePin(PIN_LED3, HIGH);
			esp8266_send(BTN3ONTEXT);
			resetIncoming();
			break;
		case BTN3RCVDOFF:
			writeI2cDisplayLine("Button3 off pressed",0,1);
			writePin(PIN_LED3, LOW);
			esp8266_send(BTN3OFFTEXT);
			resetIncoming();
			break;
		case BTN4RCVDON:
			writeI2cDisplayLine("Button4 on pressed",0,1);
			writePin(PIN_LED4, HIGH);
			esp8266_send(BTN4ONTEXT);
			resetIncoming();
			break;
		case BTN4RCVDOFF:
			writeI2cDisplayLine("Button4 off pressed",0,1);
			writePin(PIN_LED4, LOW);
			esp8266_send(BTN4OFFTEXT);
			resetIncoming();
			break;
			
		default:
			break;
	}
}

Esp8266.h

/*
 * esp8266.h
 *
 * Created: 8-2-2018 21:08:06
 *  Author: acer
 */ 


#ifndef ESP8266_H_
#define ESP8266_H_

//#define GETRECEIVED 1
#define USERDEFINEDRECEIVED 2
#define BTN1RCVDON 3
#define BTN1RCVDOFF 4
#define BTN2RCVDON 5
#define BTN2RCVDOFF 6
#define BTN3RCVDON 7
#define BTN3RCVDOFF 8
#define BTN4RCVDON 9
#define BTN4RCVDOFF 10
#define NOTHINGSET 11

#define BTN1ONTEXT "lamp on"
#define BTN1OFFTEXT "lamp off"
#define BTN2ONTEXT "tv on"
#define BTN2OFFTEXT "tv off"
#define BTN3ONTEXT "cam on"
#define BTN3OFFTEXT "cam off"
#define BTN4ONTEXT "fan on"
#define BTN4OFFTEXT "fan off"

void esp8266_init(void);
bool esp8266_send(const char* text1);
uint8_t readInComing(int timeout, const char* text1);
void resetIncoming(void);
uint8_t checkIncomingFlag(void);
char* getIP(void);

extern unsigned long int msCounter;
struct RcvFlag rcvFlag1;

struct RcvFlag {
	bool userDefinedReceived;
	bool btn1RcvdOn;
	bool btn1RcvdOff;
	bool btn2RcvdOn;
	bool btn2RcvdOff;
	bool btn3RcvdOn;
	bool btn3RcvdOff;
	bool btn4RcvdOn;
	bool btn4RcvdOff;
};


#endif /* ESP8266_H_ */

Esp8266.c

/*
 * esp8266.c
 *
 * Created: 8-2-2018 21:07:55
 *  Author: acer
 */ 

#define F_CPU 16000000UL // 16 MHz clock speed

#include <avr/io.h>
#include <util/delay.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include "timer4clocklib.h"
#include "i2cdisplay.h"
#include "uart.h"
#include "esp8266.h"



/****************************************************************************
	esp8266_init(), initialize the esp8266
****************************************************************************/
void esp8266_init(){
	
	uint8_t p;
	
	// Check the status of the ESP8266 if not ok reset
	_delay_ms(500);
	serialWrite("AT", CRLF);
	p = readInComing(1000, "OK\r\n");
	if (p != 2){
		writeI2cDisplayLine("Reset needed!", 0, 1);
		_delay_ms(4000);
		serialWrite("AT+RST", CRLF);
		p = readInComing(3000, "OK\r\n");
		if (p == 2){
			writeI2cDisplayLine("Reset done OK!", 0, 1);
			_delay_ms(1000);
		}
	}
	else{
		writeI2cDisplayLine("ESP8266 conn. OK", 0, 1);
		_delay_ms(1000);
	}
	
	// reset all flags generated by incoming data from the ESP8266 and empty the buffer.
	resetIncoming();
	
	
	// configure the server and activate the server on the ESP8266
	serialWrite("AT+CIPMUX=1", CRLF);
	p = readInComing(1000, "OK\r\n");
	if (p == 2){
		resetIncoming();
		writeI2cDisplayLine("AT+CIPMUX=1 set", 0, 1);
		_delay_ms(1000);
		serialWrite("AT+CIPSERVER=1,80", CRLF); //\r\n
		p = readInComing(1000, "OK\r\n");
		if (p == 2){
			resetIncoming();
			writeI2cDisplayLine("AT+CIPSERVER set", 0, 1);
		}
	}
	
	// init is done so clean up all flags again.
	resetIncoming();
}

/****************************************************************************
	esp8266_send, send uart data to the esp8266
****************************************************************************/
bool esp8266_send(const char* text1){
	
	int p;
	int textLength;
	char buf1[50] = {'\0'};
	char itoaBuf[3];


	if (text1 != NULL){
		strcpy(buf1, (char *) text1);
		textLength = strlen(buf1);
	}
	else{
		textLength = 0;
	}
	
	// the esp8266 requires the amount of bytes that will be send in chars.
	itoa(textLength+2, itoaBuf ,10);
	serialWrite("AT+CIPSEND=0,", NO_EOL);
	serialWrite(itoaBuf, CRLF);
	
	// the data is send wait on the esp8266 for a confirmation
	resetIncoming();
	p = readInComing(1000, "OK\r\n");
	if (p == 2){
		resetIncoming();
		writeI2cDisplayLine(buf1,0,2);
		serialWrite(buf1, CRLF);
		p = readInComing(500, "SEND OK\r\n");
		if (p == 2){
			resetIncoming();
			return true;
		}
		else{
			return false;
		}
	}
	else{
		return false;
	}
		
}

/****************************************************************************
	checkInComing, check/read data received by the esp8266
****************************************************************************/
uint8_t readInComing(int timeOut, const char* text1){ // ipv int
	
	char buf1[30] = {'\0'};
	uint8_t flag;
	
	uint8_t p; //unsigned char p;
	
	uint8_t lengthUsrDef;
	uint8_t lengthBtn1On, lengthBtn1Off, lengthBtn2On, lengthBtn2Off, lengthBtn3On, lengthBtn3Off, lengthBtn4On, lengthBtn4Off;
	
	uint8_t posUsrDef = 0;
	uint8_t posBtn1On = 0;
	uint8_t posBtn1Off = 0;
	uint8_t posBtn2On = 0;
	uint8_t posBtn2Off = 0;
	uint8_t posBtn3On = 0;
	uint8_t posBtn3Off = 0;
	uint8_t posBtn4On = 0;
	uint8_t posBtn4Off = 0;
	
	lengthBtn1On = strlen(BTN1ONTEXT);
	lengthBtn1Off = strlen(BTN1OFFTEXT);
	lengthBtn2On = strlen(BTN2ONTEXT);
	lengthBtn2Off = strlen(BTN2OFFTEXT);
	lengthBtn3On = strlen(BTN3ONTEXT);
	lengthBtn3Off = strlen(BTN3OFFTEXT);
	lengthBtn4On = strlen(BTN4ONTEXT);
	lengthBtn4Off = strlen(BTN4OFFTEXT);
	
	
	if (text1 != NULL){
		strcpy(buf1, (char *) text1);
		lengthUsrDef = strlen(buf1);
	}
	else{
		lengthUsrDef = 0;
	}
	
	flag = checkIncomingFlag();			
	if (flag != NOTHINGSET){
		return flag;
	}

	
	if(timeOut != 0){ // user gives predefined time
		unsigned long stop = msCounter + timeOut;
		do{
			p = getChar();
			while (p != 0x0){
				
				posUsrDef = (p == buf1[posUsrDef]) ? posUsrDef + 1 : 0;
				if (lengthUsrDef > 0 && posUsrDef == lengthUsrDef){ // user defined
					rcvFlag1.userDefinedReceived = true;
					return USERDEFINEDRECEIVED;
				}
				p = getChar();
			}
		}while (msCounter < stop); } else if(timeOut == 0){ // if no time out set, used in the app to continuously check for incoming data p = getChar(); while (p != 0){ posUsrDef = (p == buf1[posUsrDef]) ? posUsrDef + 1 : 0; posBtn1On = (p == BTN1ONTEXT[posBtn1On]) ? posBtn1On + 1 : 0; posBtn1Off = (p == BTN1OFFTEXT[posBtn1Off]) ? posBtn1Off + 1 : 0; posBtn2On = (p == BTN2ONTEXT[posBtn2On]) ? posBtn2On + 1 : 0; posBtn2Off = (p == BTN2OFFTEXT[posBtn2Off]) ? posBtn2Off + 1 : 0; posBtn3On = (p == BTN3ONTEXT[posBtn3On]) ? posBtn3On + 1 : 0; posBtn3Off = (p == BTN3OFFTEXT[posBtn3Off]) ? posBtn3Off + 1 : 0; posBtn4On = (p == BTN4ONTEXT[posBtn4On]) ? posBtn4On + 1 : 0; posBtn4Off = (p == BTN4OFFTEXT[posBtn4Off]) ? posBtn4Off + 1 : 0; if (lengthUsrDef > 0 && posUsrDef == lengthUsrDef){ // user defined
				rcvFlag1.userDefinedReceived = true;
				return USERDEFINEDRECEIVED;
			}
			if (lengthBtn1On > 0 && posBtn1On == lengthBtn1On){ // button 1 on
				rcvFlag1.btn1RcvdOn = true;
				return BTN1RCVDON;
			}
			if (lengthBtn1Off > 0 && posBtn1Off == lengthBtn1Off){ // button 1 off
				rcvFlag1.btn1RcvdOff = true;
				return BTN1RCVDOFF;
			}
			if (lengthBtn2On > 0 && posBtn2On == lengthBtn2On){ // button 2 on
				rcvFlag1.btn2RcvdOn = true;
				return BTN2RCVDON;
			}
			if (lengthBtn2Off > 0 && posBtn2Off == lengthBtn2Off){ // button 2 off
				rcvFlag1.btn2RcvdOff = true;
				return BTN2RCVDOFF;
			}
			if (lengthBtn3On > 0 && posBtn3On == lengthBtn3On){ // button 3 on
				rcvFlag1.btn3RcvdOn = true;
				return BTN3RCVDON;
			}
			if (lengthBtn3Off > 0 && posBtn3Off == lengthBtn3Off){ // button 3 off
				rcvFlag1.btn3RcvdOff = true;
				return BTN3RCVDOFF;
			}
			if (lengthBtn4On > 0 && posBtn4On == lengthBtn4On){ // button 4 on
				rcvFlag1.btn4RcvdOn = true;
				return BTN4RCVDON;
			}
			if (lengthBtn4Off > 0 && posBtn4Off == lengthBtn4Off){ // button 4 off
				rcvFlag1.btn4RcvdOff = true;
				return BTN4RCVDOFF;
			}
			
			p = getChar();
		}
	}
		
	return NOTHINGSET;
}

/****************************************************************************
	checkIncomingFlag, check the current status of what message is received at last
****************************************************************************/
uint8_t checkIncomingFlag(){
	

	if(rcvFlag1.userDefinedReceived == true){
		return USERDEFINEDRECEIVED;
	}
	
	else if(rcvFlag1.btn1RcvdOn == true){
		return BTN1RCVDON;
	}
	
	else if(rcvFlag1.btn1RcvdOff == true){
		return BTN1RCVDOFF;
	}
	
	else if(rcvFlag1.btn2RcvdOn == true){
		return BTN2RCVDON;
	}
	
	else if(rcvFlag1.btn2RcvdOff == true){
		return BTN2RCVDOFF;
	}
	
	else if(rcvFlag1.btn3RcvdOn == true){
		return BTN3RCVDON;
	}
	
	else if(rcvFlag1.btn3RcvdOff == true){
		return BTN3RCVDOFF;
	}
	
	else if(rcvFlag1.btn4RcvdOn == true){
		return BTN4RCVDON;
	}
	
	else if(rcvFlag1.btn4RcvdOff == true){
		return BTN4RCVDOFF;
	}
	else{
		return NOTHINGSET;
	}
}

/****************************************************************************
	resetIncoming, reset all flags to prepare for the next expected data from the esp8266
****************************************************************************/

void resetIncoming(){
	
	rcvFlag1.userDefinedReceived  = false;
	rcvFlag1.btn1RcvdOn = false;
	rcvFlag1.btn1RcvdOff = false;
	rcvFlag1.btn2RcvdOn = false;
	rcvFlag1.btn2RcvdOff = false;
	rcvFlag1.btn3RcvdOn = false;
	rcvFlag1.btn3RcvdOff = false;
	rcvFlag1.btn4RcvdOn = false;
	rcvFlag1.btn4RcvdOff = false;
}


/****************************************************************************
	getIP, just to know the IP as i forgot to make it static instead of dhcp...
****************************************************************************/

char* getIP(){
	
	uint8_t p;
	int posIpReceived = 0;
	char matchStaip[] = "STAIP,\"";
	int ipCharsCounter = 0;
	int staIpLength = strlen(matchStaip);
	static char tempBuffer[16];
	bool matched = false;
	
	serialWrite("AT+CIFSR", CRLF);
	_delay_ms(200); // wait for all the data from this cmd
	p = getChar();
	while (p != 0x0){
		
		if(p == matchStaip[posIpReceived]){
			posIpReceived++;
		}
		else{
			posIpReceived = 0;
		}
		
		if (staIpLength > 0 && posIpReceived == staIpLength){ // STAIP received
			matched = true;
		}
		
		if(matched == true){
			tempBuffer[ipCharsCounter] = p;
			ipCharsCounter++;
			if (ipCharsCounter > 16){
				ipCharsCounter = 0;
				matched = false;
				return tempBuffer;
			}
			
		}
		p = getChar();
	}
	
	return NULL;
	
}

Uart.h

/*
 * uart.h
 *
 * Created: 8-12-2017 13:36:22
 *  Author: acer
 */


#ifndef UART_H_
#define UART_H_

/****************************************************************************
	Bit and byte definitions
****************************************************************************/
#define CLOCKSPEED_CPU   16000000
#define BAUD    57600
#define BRC     ((CLOCKSPEED_CPU/16/BAUD) - 1)
#define TX_BUFFER_SIZE  40
#define RX_BUFFER_SIZE  200 // it's a bit big because of the CIFSR cmd returns a lot of bytes used in getIp()
#define CR 1
#define LF 2
#define CRLF 3
#define NO_EOL 4



/****************************************************************************
	Function definitions
****************************************************************************/

void UART_Init();
void serialWrite(char c[], uint8_t eol);
void UART_Transmit(unsigned char data );
char getChar(void);


#endif /* UART_H_ */

Uart.c

/*
 * uart.c
 *
 * Created: 8-12-2017 13:36:09
 *  Author: acer
 */ 

#define F_CPU 16000000UL // 16 MHz clock speed


#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdbool.h>
#include "uart.h"


/****************************************************************************
	Bit and byte definitions
****************************************************************************/
char rxBuffer[RX_BUFFER_SIZE];
uint8_t rxWritePos = 0;
uint8_t rxReadPos = 0;


/****************************************************************************
	USART_Init, see important info below
****************************************************************************/
void UART_Init(){

	UBRR0H = (unsigned char)(BRC >> 8); //baud rate register set to 9600 BAUD
	UBRR0L = (unsigned char) BRC;

	UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1 << RXCIE0);
	UCSR0C = (1 << UCSZ01) | (3<<UCSZ00);
}


/****************************************************************************
	serialWrite, send data with optional crlf
****************************************************************************/
void serialWrite(char c[], uint8_t eol)
{
	int i;
	
	for(i = 0; i < strlen(c); i++)// put the string you want to write in a buffer. { UART_Transmit(c[i]); //put the char's one by one in the buffer } if (eol == CR){ UART_Transmit(0xd); //CR \r } else if (eol == LF){ UART_Transmit(0xa); //LF \n } else if (eol == CRLF){ UART_Transmit(0xd); //CR \r UART_Transmit(0xa); //LF \n } else if (eol == NO_EOL){ return; } } /**************************************************************************** ISR(USART_RX_vect), Fills up a buffer. ****************************************************************************/ ISR(USART_RX_vect) { rxBuffer[rxWritePos] = UDR0;// rxWritePos++; if(rxWritePos >= RX_BUFFER_SIZE)
	{
		rxWritePos = 0;
	}

}

/****************************************************************************
	USART_Transmit, 
****************************************************************************/
void UART_Transmit(unsigned char data ){
	
	while( !( UCSR0A & (1<<UDRE0)) ); // Wait for empty transmit buffer UDR0 = data; // Put data into buffer, sends the data } /**************************************************************************** getChar, ****************************************************************************/ char getChar(void) { char ret = '\0'; _delay_us(500); // to prevent reading faster then the bytes are coming in if(rxReadPos != rxWritePos) { ret = rxBuffer[rxReadPos]; rxReadPos++; if(rxReadPos >= RX_BUFFER_SIZE)//
		{
			rxReadPos = 0;
		}
	}
	
	return ret;
}

 

Thanks for reading!