Передача Email с использованием микроконтроллера AVR ATmega16 и ESP8266

ATmega16 (семейство AVR) является дешевым 8 битным микроконтроллером и имеет достаточно большое число интерфейсов ввода-вывода общего назначения. Он поддерживает все часто используемые в настоящее время протоколы связи такие как UART, USART, SPI и I2C. Он достаточно широко применяется в робототехнике, автомобилестроении и автоматизированных производствах из-за своей простоты и универсальности.

Подключение ESP8266 к микроконтроллеру AVR ATmega16: внешний вид

Но, к сожалению, ATmega16 не поддерживает никакие беспроводные протоколы связи, такие как, например, Wi-Fi и Bluetooth. Это обстоятельство существенно ограничивает его применение в такой сфере как интернет вещей (IoT), которая считается очень перспективной в современных реалиях. Чтобы преодолеть это ограничение к микроконтроллеру ATmega16 необходимо подключить устройство, которое поддерживало бы беспроводные протоколы связи. Таких устройств сейчас существует много, но одним из наиболее широко используемых является ESP8266.

В этой статье мы рассмотрим подключение микроконтроллера AVR ATmega16 к устройству управления многосторонней связью (NodeMCU) ESP8266 чтобы при помощи беспроводной связи, обеспечиваемой данным устройством, получить доступ в интернет. ESP8266 представляет собой WiFi модуль с поддержкой различных протоколов связи и множеством доступных библиотек.

Мы рассмотрим передачу email (электронной почты) с использованием ESP8266 и микроконтроллера ATmega16. ATmega16 будет давать команды ESP8266, которое будет пересылать email выбранному корреспонденту. ATmega16 и ESP8266 будут взаимодействовать через универсальный асинхронный приемопередатчик (UART), хотя можно использовать и другие доступные ATmega16 протоколы связи, такие как SPI и I2C.

Некоторые особенности поставленной задачи

Необходимо помнить о том, что микроконтроллер ATmega16 работает от напряжения 5В, а микросхема ESP8266 – от напряжения 3.3В. То есть логические уровни между этими двумя устройствами отличаются, что может вызвать «недопонимание» между ними и даже потерю данных если необходимые логические уровни не будут поддерживаться.

Но, тем не менее, если внимательно изучить технические характеристики (datasheet) микросхемы ESP8266, можно обнаружить что она терпимо (толерантно) относится к напряжению до 6В на своих контактах, поэтому ESP8266 сможет «понимать» логический уровень напряжения 5В. Также в даташите на ATmega16 указано, что уровень напряжения больший 2В он воспринимает как логическую единицу и, поскольку, ESP8266 оперирует напряжением 3.3В, то сигнал такого уровня будет восприниматься микроконтроллером как логическая «1». Поэтому взаимосвязь между этими устройствами можно организовать без переключения логических уровней напряжения.

Необходимые компоненты

Микроконтроллер ATmega16
Источник питания с напряжением 5 Вольт
Программатор AVR-ISP, USBASP или другой подобный
Устройство управления многосторонней связью (NodeMCU) ESP8266
Кварцевый генератор на 16 МГц
Конденсатор 100 нФ (2 шт.)
Конденсатор 22 пФ (2 шт.)
Кнопка
Соединительные провода
Макетная плата
Светодиод

Схема подключения ESP8266 к микроконтроллеру ATmega16

Схема устройства приведена на следующем рисунке.

Схема подключения ESP8266 к микроконтроллеру ATmega16

Конфигурирование SMTP2GO сервера для передачи Email

Перед тем как начать программировать микроконтроллер нам нужно сконфигурировать SMTP сервер чтобы осуществлять передачу Email (электронной почты) при помощи ESP8266. Для выполнения этой задачи можно использовать сайт smtp2go.com.

Для начала нам будет необходимо имя пользователя и пароль для SMTP. Для их получения выполните следующие шаги:

Шаг 1: Кликните на “Try SMTP2GO Free” чтобы зарегистрировать бесплатный аккаунт.

Главная страница сайта smtp2go.com

Шаг 2. Откроется окно, в котором вы должны будете ввести имя, email и пароль.

Страница регистрации на сайте smtp2go.com

Шаг 3. После заполнения всех этих полей и нажатия кнопки «sign up» вам на указанную электронную почту придет запрос на активацию вашего аккаунта. Кликните на полученную ссылку для активации вашего аккаунта и затем войдите на smtp2go.com используя ваш email и пароль.

Шаг 4. После того как вы войдете на сайт со своими учетными данными сразу же после этого вам будет предоставлен ваш SMTP Username (имя пользователя) и ваш SMTP Password (пароль). Запомните или запишите где-нибудь эти данные. После этого нажмите на ‘finish’.

Установка имени пользователя и пароля

Шаг 5. Затем в левом меню кликните сначала на “Settings”, а потом на “Users”. В этих разделах вы можете посмотреть информацию про ваш SMTP Server и номер порта (PORT number). К примеру, как показано на следующем рисунке.

Страница настроек SMTP сервера

После этого необходимо декодировать имя пользователя (Email) и пароль из формата ASCII в формат base64. Для этой цели можно использовать сайт BASE64ENCODE. Конвертированные имя пользователя и пароль сохраните чтобы можно было ими пользоваться в дальнейшем.

Главная страница сайта https://www.base64encode.org/

После выполнения всех этих действий можно приступить к программированию микроконтроллера ATmega16 и модуля беспроводной связи ESP8266.

Программирование микроконтроллера AVR ATmega16 и ESP8266

Необходимы будут две программы: одна для ATmega16, который будет действовать как передатчик команд, и вторая для ESP8266, который будет работать как приемник команд. Обе программы приведены в конце данной статьи. Для загрузки программы в ATmega16 можно использовать программатор USBasp, а для загрузки программы в модуль ESP8266 — Arduino IDE.

Также к микроконтроллеру ATmega16 подключим одну кнопку – при ее нажатии микроконтроллер передает команды в ESP8266, а ESP8266 в соответствии с ними осуществляет передачу электронной почты. Светодиод будет показывать статус (состояние) процесса передачи данных.

Исходный код программы для ATmega16 с пояснениями

Начнем с задания тактовой частоты микроконтроллера и подключения всех необходимых библиотек. Все используемые библиотеки находятся в Atmel Studio Package.

#define F_CPU 16000000UL
#include<avr/io.h>
#include<util/delay.h>
#include <stdlib.h>
#include <stdio.h>

После этого необходимо определиться с бодовой скоростью передачи последовательного порта, который мы будем использовать для связи микроконтроллера с ESP8266. Эта скорость будет одинаковой и для ATmega16, и для ESP8266. Выберем скорость передачи равную 9600 бод/с.

#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

Регистры UBRRL и UBRRH будут использоваться для загрузки значения скорости передачи. Нижние 8 бит скорости передачи будут загружаться в UBRRL, а верхние 8 бит – в UBRRH. Для упрощения нашей задачи запрограммируем функцию для инициализации универсального асинхронного последовательного приемопередатчика (UART), в которой входным параметром будет требуемая скорость передачи. Эта функция будет включать:

  1. Установку битов приема и передачи в регистре UCSRB.
  2. Выбор 8-битного размера символа в регистре UCSRC.
  3. Загрузка нижних и верхних бит бодовой скорости в регистры UBRRL и UBRRH.

void UART_init(long USART_BAUDRATE)
{
UCSRB |= (1 << RXEN) | (1 << TXEN);
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
UBRRL = BAUD_PRESCALE;
UBRRH = (BAUD_PRESCALE >> 8);
}

Далее запрограммируем функцию, которая будет отвечать за передачу одного символа. Данная функция будет ждать до тех пор, пока буфер не будет чист, а затем будет загружать значение символа в регистр UDR.

void UART_TxChar(char c)
{
while (! (UCSRA & (1<<UDRE)));
UDR = c;
}

Вместо того чтобы передавать каждый символ по отдельности, запрограммируем функцию, которая будет передавать сразу целую строку символов.

void UART_sendString(char *str)
{
unsigned char s=0; while (str[s]!=0)
{
UART_TxChar(str[s]);
s++;
}
}

В главной функции main() сделаем вызов UART_init() чтобы начать передачу, а также сделаем эхотест (echo test) при помощи передачи строки «TEST» на модуль ESP8266.

UART_init(9600);
UART_sendString("TEST");

Начнем конфигурирование контактов ввода-вывода общего назначения для светодиода и кнопки.

DDRA |= (1<<0);
DDRA &= ~(1<<1);
PORTA |= (1<<1);

Если кнопка не нажата оставляем светодиод во включенном состоянии. Если кнопка нажата, то начинаем передачу данных (передаем команду “SEND”) на модуль ESP8266 и выключаем светодиод.

if(bit_is_clear(PINA,1))
{
PORTA |= (1<<0);
_delay_ms(20);
}
else
{
PORTA &= ~(1<<0);
_delay_ms(50);
UART_sendString("SEND");
_delay_ms(1200);
}

Исходный код программы для модуля беспроводной связи ESP8266

Программирование модуля ESP8266 будет заключаться в приеме команд от микроконтроллера Atmega16 и передачи Email используя полученный нами SMTP сервер.

Сначала подключим библиотеку WiFi чтобы у нас был доступ к интернету для передачи электронной почты. Определите ваш WiFi идентификатор (ssid) и пароль для осуществления успешного соединения с интернетом. Также определите ваш SMTP сервер.

#include <ESP8266WiFi.h>
const char* ssid = "xxxxxxxxxxxx";
const char* password = "xxxxxxxxxxx";
char server[] = "mail.smtp2go.com";

В функции setup() задайте бодовую скорость передачи 9600 бод/с (такую же как и у Atmega16), произведите соединение с WiFi и отобразите IP адрес.

Serial.begin(9600);
Serial.print("Connecting To: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500); Serial.print(".");
}

В функции loop() прочтите принятые байты с контакта Rx и конвертируйте их в строку.

if ( Serial.available() > 0 ) {
while (Serial.available() > 0 && index1 < 6)
{
delay(100);
inChar = Serial.read();
inData[index1] = inChar;
index1++;
inData[index1] = '\0';
}
variable.toUpperCase();
for (byte i = 0 ; i < 6 ; i++) {
variable.concat(String(inData[i]));
}
Serial.print("variable is = "); Serial.println(variable);
Serial.print("indata is = "); Serial.println(inData);
delay(20);
}
String string = String(variable);

Если принимаемая команда опознана, то выполните передачу email адресату при помощи вызова функции sendEmail().

 if (string == "SEND") {
sendEmail();
Serial.print("Mail sent to:"); Serial.println(" The recipient");
Serial.println("");
}

Результат передачи тестового Email

Необходимо отметить, что очень важно сконфигурировать SMTP сервер потому что без этого шага email не будет отправляться. Также необходимо установить одинаковые скорости передачи данных для микроконтроллера Atmega16 и модуля ESP8266.

Если вы успешно осуществите все действия, которые описаны в данной статье, то вы сможете успешно интегрировать микроконтроллер AVR в любой проект, связанный с интернетом вещей (IoT).

Полный текст программы

Для модуля беспроводной связи ESP8266

В представленном коде программы там, где вы видите последовательность симоволов «// ********************», необходимо изменить значения переменных на свои данные: имя пользователя, пароль, email и т.д.

#include <ESP8266WiFi.h>
const char* ssid = "xxxxxxxxx"; // введите SSID вашей WiFi сети.  //********************
const char* password = "xxxxxxxxxx"; // введите пароль вашей WiFi сети. // ********************
char server[] = "mail.smtp2go.com"; // напишите адрес вашего SMTP сервера // ********************
WiFiClient Client; //определите wifi клиент в качестве клиента
void setup() {
delay(1000);
Serial.begin(9600); // установка скорости 9600 бод/с
Serial.println("");
Serial.print("Connecting To: ");
Serial.println(ssid);
WiFi.begin(ssid, password); // соединение с WIFI
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi Connected.");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
char inChar = 0;
char inData[6] = ""; // длина данных 6 символов
String variable = "";
String variable1 = "";
int index1 = 0;

if ( Serial.available() > 0 ) { // Read from Rx from atmega16
while (Serial.available() > 0 && index1 < 6) // read till 6th character
{
delay(100);
inChar = Serial.read(); // старт последовательной передачи и сохранение в переменную
inData[index1] = inChar;
index1++;
inData[index1] = '\0'; // добавляем ноль в конец
}
variable.toUpperCase(); // конвертируем в заглавные буквы (uppercase)
for (byte i = 0 ; i < 6 ; i++) {
variable.concat(String(inData[i])); // объединяем строки
}
Serial.print("Variable = "); Serial.println(variable); // печатаем входные данные
delay(20);
}
String string = String(variable); // строка, которая будет использоваться для сравнения

if (string == "SEND") { // если принимаемые данные = "SEND" то передаем email
sendEmail(); // передаем email
Serial.print("Mail sent to:"); Serial.println(" The recipient"); // debug if sent
Serial.println("");
}
}
byte sendEmail()
{
if (Client.connect(server, 2525) == 1) // connect to smtp server with port address 2525
{
Serial.println(F("connected to server"));
}
else
{
Serial.println(F("connection failed"));
return 0;
}
if (!emailResp()) // если соединение не удалось, то возврат
return 0;
//
Serial.println(F("Sending EHLO"));
Client.println("EHLO http://www.example.com/"); // Send command EHLO previosly it was HELO
if (!emailResp())
return 0;

Serial.println(F("Sending auth login"));
Client.println("AUTH LOGIN");
if (!emailResp())
return 0;
//
Serial.println(F("Sending User"));

// в этом месте (в операторе Client.println ) вам будет необходимо заменить строку на ваше имя пользователя SMTP в формате base64
// к примеру адрес email dummy@gmail.com в формате base64 будет выглядеть следующим образом: djfdBDBEDEJD545616vfbSJHB=

Client.println("Y2lyY3VpdGRxxxxxxxxxxxxxdtYWlsLmNvbQ=="); //base64, ASCII encoded SMTP Username ********************
if (!emailResp())
return 0;
Serial.println(F("Sending Password"));

// аналогично меняем в операторе Client.println строку на ваш SMTP пароль в формате base64
// к примеру пароль "password" будет выглядеть в формате base64 IBjbjHUInOUi4654==

Client.println("Y2lyY3VpdxxxxxxzdA=="); //base64, ASCII encoded SMTP Password ********************

if (!emailResp())
return 0;
//
Serial.println(F("Sending From"));
// изменить на нужный вам адрес email (ваш email)
Client.println(F("MAIL From: dummy@gmail.com")); // ********************
if (!emailResp())
return 0;
// изменить на адрес email вашего адресата (получателя)
Serial.println(F("Sending To"));
Client.println(F("RCPT To: test@gmail.com")); // ********************

if (!emailResp())
return 0;
//
Serial.println(F("Sending DATA"));
Client.println(F("DATA"));
if (!emailResp())
return 0;
Serial.println(F("Sending email"));
// изменить на адрес получателя
Client.println(F("To: test@gmail.com")); // ********************
// изменить на ваш адрес
Client.println(F("From: dummy@gmail.com")); //********************
Client.println(F("Subject: ESP8266 test e-mail\r\n"));
Client.println(F("This is is a test e-mail sent from ESP8266.\n"));
Client.println(F("Second line of the test e-mail."));
Client.println(F("Third line of the test e-mail."));
//
Client.println(F("."));
if (!emailResp())
return 0;
//
Serial.println(F("Sending QUIT"));
Client.println(F("QUIT"));
if (!emailResp())
return 0;
//
Client.stop();
Serial.println(F("disconnected"));
return 1;
}
byte emailResp()
{
byte responseCode;
byte readByte;
int loopCount = 0;
while (!Client.available())
{
delay(1);
loopCount++;
// ждем 20 секунд и если ничего не принимаем в это время, то останов
if (loopCount > 20000)
{
Client.stop();
Serial.println(F("\r\nTimeout"));
return 0;
}
}
responseCode = Client.peek();
while (Client.available())
{
readByte = Client.read();
Serial.write(readByte);
}
if (responseCode >= '4')
{
// efail();
return 0;
}
return 1;
}

Для микроконтроллера ATmega16

#define F_CPU 16000000UL // задание тактовой частоты микроконтроллера
#include<avr/io.h>
#include<util/delay.h>
#include <stdlib.h>
#include <stdio.h>

#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) // задание коэффициента деления предделителя для установки нужного значения бодовой скорости

void UART_init(long USART_BAUDRATE)
{
UCSRB |= (1 << RXEN) | (1 << TXEN); // установка битов RX и Tx последовательного порта
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // используем 8 битный размер символа
UBRRL = BAUD_PRESCALE; // загружаем нижние 8 бит значения бодовой скорости
UBRRH = (BAUD_PRESCALE >> 8); // загружаем верхние 8 бит значения бодовой скорости
}

void UART_TxChar(char c)
{
while (! (UCSRA & (1<<UDRE))); // ждем опустошения буфера передачи
UDR = c;
}

void UART_sendString(char *str)
{
unsigned char s=0;
while (str[s]!=0) // цикл до конца строки
{
UART_TxChar(str[s]); // send s to UART_TxChar(s) function
s++;
}
}

int main(void)
{

UART_init(9600); // инициализируем UART для скорости 9600 бод/с

UART_sendString("TEST");
//DDR – регистр направления данных
DDRA |= (1<<0); //устанавливаем pin0 of PORTA в режим вывода поскольку к нему подключен светодиод
DDRA &= ~(1<<1); //устанавливаем pin1 of PORTA в режим ввода поскольку к нему подключена кнопка
PORTA |= (1<<1); // на pin 1 устанавливаем высокий потенциал

while(1)
{
if(bit_is_clear(PINA,1)) // если кнопка не нажата
{
PORTA |= (1<<0); // включаем светодиод
_delay_ms(20);
}
else
{ // если кнопка нажата, то передаем команду "SEND" по последовательному порту
PORTA &= ~(1<<0); // выключаем светодиод
_delay_ms(50);
UART_sendString("SEND"); // передаем строку
_delay_ms(1200);
}
}
}

Видео, демонстрирующее работу схемы

(1 голосов, оценка: 5,00 из 5)
Загрузка...
166 просмотров

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *