SIM900D+ATmega


• О проекте
• Обратная связь
• Полезные ссылки
• Полезные программы
• Друзья сайта


Последние комментарии

АНОНИМ: Цифровой термометр с уличным датчиком на bluetooth модулях
Эхх) жаль( а библ...

Алексей: Цифровой термометр с уличным датчиком на bluetooth модулях
Не. Там было мног...




           

Библиотека для AVR





AXLIB Генератор





Помощь сайту


   
				

SIM900D+ATmega

	
	
	

Дата: 6 Июля 2014. Автор: Алексей

	
	
Отладочная плата на базе SIM900D

По просьбе трудящихся продолжаю тему GSM девайсов, а именно подключение модуля SIM900D к ATmega. Какая модель это не важно. В этой статье я буду использовать ATmega8515. Этот контроллер я использовал исключительно по фен-шую))) Вся нужная информация будет выводится на ЖК дисплей 20х4 фирмы МЭЛТ. Его тоже выбирал по фен-шую))) И также потому что он понимает кодировку Windows-1251 что сильно упрощает вывод русских буковок.

Вывод информации на ЖК дисплей

А теперь собственно поставим задачу.


Задача поставлена. GSM-модуль общается с МК по UART. Схема включения GSM-модуля можно посмотреть здесь. МК будет работать на частоте 3,6864 МГц. Это нужно для снижения ошибок в UART. Скорость обмена 19200. За все время тестирования ошибок с передачей не было. Правда помер один МК, что дало головомойки на пару дней, но потом с заменой на новый МК все пошло как по маслу. ЖК дисплей подключен к порту А. Порт С отдан на включение и выключение светодиодов. Ах да. тут есть один нюанс. GSM-модуль может получать данные на ногу RxD только 3 вольта и не более!!! Это важно!!! Отсюда было принято решение подавать данные через резисторный делитель. Расчет плечей оставляю за вами так как МК может работать в разных диапазонах от 2,8 до 5 вольт. Лично я питаю GSM-модуль 4 вольтами, а МК 5. Так, с железом вроде разобрались. Теперь поехали по коду. Первое что необходимо это способ принятия данных от GSM-модуля. Модуль пуляет ответы на запросы такого вида:
Запрос:
AT+CSQ\r\r\n
Ответ:
\r\n+CSQ: 17,0\r\n\r\nOK\r\n
Отсюда видно что запросы и ответы перемешаны кучей \r и \n ерундой. Ну для запроса это не проблема, так как мы сами его пишем, а вот ответ... Разгребать весь этот зоопарк каждым пришедшим байтом в UDR не комельфо, поэтому будем использовать кольцевой буфер. Кто не знает что это, идем сюда. При использовании кольцевого буфера добавим в обработчик прерывания по приходу данных в UDR проверку для игнорирования \r и \n.


ISR(USART_RX_vect)
{
    char temp = UDR;
    if(!(temp == 0x0A || temp == 0x0D)) InBuffer(temp);
}


То есть мы записываем в буфер все кроме \r и \n. Как только мы получили данные начинаем их обрабатывать. Первое что нужно посмотреть, SMS это или ответ на команду. Так как GSM-модуль всегда возвращает фиксированный ответ, а меняет только данные, то отследить можно по названию ответа. Например запрос на уровень приема GSM.


if(time == 30)
{
    time = 0;
    USART_STR("AT+CSQ"); 
    USART_END();
    _delay_ms(200);
}
		
if(GetData())
{
    _delay_ms(70);
    num = IndexNumber();
    OutBufferStr(temp,num);
}


Теперь в массиве temp лежит ответ от GSM-модуля. Теперь давайте его распознаем.


if((temp[1] == 'C') & (temp[2] == 'S') & (temp[3] == 'Q'))
{
}

Если в массиве лежит ответ на запрос уровня GSM, то условие выполнится и его можно обрабатывать по своему усмотрению. А если условие не выполнилось? То скорее всего пришло SMS. Как его вычислить? Как только приходит SMS сообщение, модуль возвращает строку вида.


+CMTI: "SM",1


Все что здесь меняется, так это последний символ, а точнее цифра. Это номер SMS. А вот буквы SM не меняются никогда. Значит нам требуется проверить есть ли в сообщении эти буквы.


if((temp[8] == 'S') & (temp[9] == 'M'))
{
}


Конечно еще бы было не плохо проверить название самой команды для более точного убеждения, но я этим пренебрег так как это пока просто объяснения работы МК с GSM-модулем. Поле того как распознали принятие SMS не плохо бы было его прочитать. Кидаем GSM-модулю запрос вида.


USART_STR("AT+CMGR=");
USART_TXD(temp[12]);
USART_STR(",0");
USART_END();
_delay_ms(200);


В ячейке массива temp[12] лежит номер SMS. Данная команда будет адекватна при SMS сообщениях меньше 9. Ну это понятно почему. А вообще чтобы не забивать память SIM карты SMSками я после прочтения SMS сразу удаляю ее, поэтому больше 1 SMS в памяти не бывает. Но все же я использовал не жестко число 1, а именно выдрал его из массива. Я не знаю почему, но иногда SMS не всегда приходят сразу, а с неким опозданием. Если такое произошло, то возможен такой косяк, SMSка еще не пришла, мы думаем что не прошла и шлем за ней еще одну. Тут проходит время и они приходят две подряд одна за одной. Первую мы читаем как 1, а вторая пришла как 2. Вот от таких косяков и защищает ячейка массива. Теперь запросив текст SMS GSM-модуль вернет нам ответ вида.


+CMGR: "REC UNREAD","+71234567890","","14/07/06,13:04:38+16" сообщение OK


После этого можно читать сообщение. Так как ответы всегда фиксированы, то можно смело начинать читать с temp[60]... и может возникнуть косяк))) Я на него нарвался. Пока я разбирался с GSM-модулем мне тихим сапом Beeline прислал SMSку. Все бы ничего да подстава засела в месте где прописывается номер отправляющего SMS абонента. Вместо "+71234567890" мне пришло "My Beeline". Ну понятно чем это пахнет. Короче МК ни фига не понял и вошел в ступор. Поэтому я решил все таки проверять номер. Да и для безопасности это не помешает. А то вдруг зависливый сосед прознает про управление котлом по SMS и пошлет команду зимой выключит котел))).


for(uint8_t i=0; i<12; i++)   
{
    if(temp[i+21] == phone[i]) 
    {
        flag=1;
    }
    else
    {
        flag=0;
        break;
    }	
}


Смысл прост. В цикле сравниваем ячейки массива буфера отвечающие за номер с массивом в который заранее положили требуемый номер. Пока цифры совпадают флаг равен 1, но как только цифра не совпадет, обнуляем флаг и выходим из цикла. Если флаг в нуле, то не читаем SMSку, а если в единице, то SMSка наша. Если все проверки прошли, то читаем команду. Команды я сделал такие. Заглавния буква V значит включить, O значит отключить. Для того чтобы узнать какой светодиод включить или выключить, после буквы пишем его номер от 1 до 8. Пример, нужно включить 4-й светодиод. Шлем SMS с текстом V4, а для отключения O4.

<
if(flag) 
{					
    if(temp[60] == 'V') 
    {
        lcd_xy(0,2);
        lcd_putsf("LED-");
        lcd_putchar(temp[61]);
        lcd_putsf(" Bключен    ");
					
        switch (temp[61])
        {
            case 0x31: PORTC |= (1<<7);
                 break;
            case 0x32: PORTC |= (1<<6);
                 break;
            case 0x33: PORTC |= (1<<5);
                 break;
            case 0x34: PORTC |= (1<<4);
                 break;
            case 0x35: PORTC |= (1<<3);
                 break;
            case 0x36: PORTC |= (1<<2);
                 break;
            case 0x37: PORTC |= (1<<1);
                 break;
            case 0x38: PORTC |= (1<<0);
                 break;
        }
    }
			
    if(temp[60] == 'O')
    {
        lcd_xy(0,2);
        lcd_putsf("LED-");
        lcd_putchar(temp[61]);
        lcd_putsf(" Отключен    ");
			
        switch (temp[61])
        {
            case 0x31: PORTC &= ~(1<<7);
                 break;
            case 0x32: PORTC &= ~(1<<6);
                 break;
            case 0x33: PORTC &= ~(1<<5);
                 break;
            case 0x34: PORTC &= ~(1<<4);
                 break;
            case 0x35: PORTC &= ~(1<<3);
                 break;
            case 0x36: PORTC &= ~(1<<2);
                 break;
            case 0x37: PORTC &= ~(1<<1);
                 break;
            case 0x38: PORTC &= ~(1<<0);
                 break; 
        }
    }
}


Собственно вот весь код. Сначала проверяем буковку и по ней выполняем ту или иную команду и параллельно выводим сообщение на ЖК. А после того как закончили работу с SMS скидываем флаг и удаляем все SMS.


USART_STR("AT+CMGD=1,4");
USART_END();
_delay_ms(100);
					
flag=0;


Отладочная плата на базе SIM900D

Вот и все. Ниже видео всего этого безобразия и архив с проектом.

Проект GSM+ATmega8535
JW Player goes here



Vl    04.03.15 12:01

Подскажите пожалуйста Fuse биты для данного проекта для PonyProg. Заранее спасибо!

Алексей    04.03.15 21:11

Вот где не помогу, так это тут. Я даже не знаю как выглядит PonyProg. Скачайте лучше дудку. usbasp-avrdude-prog

Михаил    07.06.15 16:13

Скажите пожалуйста на чем была компилирована эта программа?

Алексей    07.06.15 18:29

AtmelStudio 6.2

Михаил    08.06.15 22:18

Подскажите, а разве в начале не нужно отправлять команду, которая настраивает GSM режим? ведь иначе нельзя будет прочитать текст сообщения.

Алексей    09.06.15 08:41

Телефон службы СМС сообщений нужно было вводить в далеких 90-х. Сейчас при покупке сим карты в ней уже все забито. Единственная команда нужна, так это отключение эхо, дабы не читать собственные команды.

okumurapanda@gmail.com.    13.08.16 19:01

Как всё это оформить на ATmega32a

Алексей    13.08.16 19:47

Собрать проект под 32 мегу. UART платформо независим.

V    04.05.17 23:32

Всё- таки не понятно, как мы принимаем решение, что пора лопатить буфер. Мы же не знаем по идее какой длинны от модема будет ответ и вообще какой. Признаков что модем передал всё что хотел передать - нету...

Алексей    05.05.17 19:59

Все очень просто. В кольцевом буфере есть функция GetData(). Данная функция возвращает количество байт записанные в буфер в данный момент. Если данные не пришли, то возвращает 0. Таким образом в теле программы постоянно вызываем данную функция и проверяем на наличие данных в буфере. Как только что-то появилась, то делаем задержку на 70мс, а потом получаем данные из буфера. За 70мс модуль передает весь пакет.




Чтобы вставить ссылку используйте форму вида[url]http://www.адрес.ru[/url][text]текст ссылки[/text]
Чтобы вставить код используйте форму вида[code]код[/code]

Имя:   





  








Вверх


Рейтинг@Mail.ru Яндекс.Метрика