Ниже показан пример исходного кода беспроводного датчика влажности с возможностью "дергания" пинов на языке Си для микроконтроллеров AVR.Проект можно легко адаптировать под другие микроконтроллеры. Структура отправляемых данных должна соответствовать массиву в файле nRF-USB.h исходного кода клиентской утилиты nRF24L01+USB.

Клиент подойдет и для варианта шлюза Ethernet-nRF24L01.

Порядок данных массива: 1 байт номер клиента, 2 байта чтения analogread,1 байт свободный,2 байта счетчик ошибок,4 байта счетчик передач,4 байта тип float температура,4 байта тип float влажность.

Исходный код подходит для м/к Atmega 328, Atmega168, Atmega88, Atmega48, Atmega8 и других.Данный пример подстроен под использование м/к Atmega8 - он  дешевый и в его помещается данный пример с большим запасом.

Функция чтения датчика влажности используется универсальная с автоматическим определением  со странички Датчики влажности DHT11 и DHT22.

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

Архив с исходным кодом и необходимыми библиотеками можно скачать тут. Обновлено 14.08.14.

Исходный код беспроводного датчика:

#define chclient 1 // номер клиента 1...
#define timeoutper 400 // таймаут запросов от сервера.
#define timesend 100 // интервал отправки данных,для обычных датчиков можно установить время выше.

#define DHT_PORT        PORTC
#define DHT_DDR         DDRC
#define DHT_PIN         PINC
#define DHT_BIT         3

#define nofloat 0 // без float , данные передаются умноженные на 10.Очень экономит место.

// Настройка nRF
#define ce_pin 0
#define csn_pin 1
#define csport PORTD
#define ceport PORTD
#define csddr DDRD
#define ceddr DDRD

#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>  /* for sei() */
#include <util/delay.h>     /* for delayMicroseconds() */
#include <avr/pgmspace.h> 

//#include <avr/eeprom.h>

#include "spi.c"
#include "ml.c"
#include "nRF.c"

// структура принятых данных.МЕНЯТЬ НЕЛЬЗЯ
typedef struct{
uint8_t identifier;
uint8_t val1;
uint8_t val2;
uint8_t val3;
uint8_t val4;
}
nf0;
nf0 servernf;

// структура отправляемых данных.Изменяемые данные.Размер структуры должен быть не больше 32 байт !
typedef struct{
  uint8_t identifier;// номер передатчика.МЕНЯТЬ НЕЛЬЗЯ

  int Analog;
  uint8_t test_data;
  int Error_Message; // счетчик ошибок
  long count;// счетчик передач для контроля качества канала
#if nofloat
int temperature_Sensor; //передаём температуру.
int Humidity_Sensor;// передаём влажность
#else
 float temperature_Sensor;// передаём температуру.
 float Humidity_Sensor;// передаём влажность
#endif
}
nf1;
nf1 clientnf; 

unsigned long time1=0;
unsigned long time2=0;

unsigned char datadht[5];

uint8_t dhtread ()
{

uint8_t  j = 0, i = 0;
    
datadht[0] = datadht[1] = datadht[2] = datadht[3] = datadht[4] = 0;  
   
DHT_DDR|=(1<<DHT_BIT); //pin as output
DHT_PORT&=~(1<<DHT_BIT); //0
_delay_ms(18);


DHT_PORT|=(1<<DHT_BIT); //1
DHT_DDR&=~(1<<DHT_BIT); //pin as input
//=============check DHT11 response
_delay_us(51); // +1
if (DHT_PIN&(1<<DHT_BIT)) return 0;
_delay_us(81); // +1
if (!(DHT_PIN&(1<<DHT_BIT))) return 0;

//===============receive 40 data bits
while (DHT_PIN&(1<<DHT_BIT));
for (j=0; j<5; j++)
    {
    datadht[j]=0;
    for(i=0; i<8; i++)
        {
        while (!(DHT_PIN&(1<<DHT_BIT)));
        _delay_us (30);
        if (DHT_PIN&(1<<DHT_BIT)) 
            datadht[j]|=1<<(7-i);
        while (DHT_PIN&(1<<DHT_BIT));
        }
    }
	
	return 1;
}
//------------------------------------------------
//-----------------Main программа-----------------
//------------------------------------------------

int __attribute__((noreturn)) main(void)
{

    DDRC |= _BV(0); //1  /* make the LED bit an output */
    DDRC |= _BV(1); //2

    
    TCCR0=(1 << CS01)|(1 << CS00); // делитель
TCNT0 = 0; // счетчик таймера, тик 10 миллисекунд
TIMSK = (1 << TOIE0); // разрешить прерывание таймера
   
radiobegin();

//эти данные и так установлены в radiobegin:
//setDataRate(2); // 1 - 250кб , 2 - 1 мб , 3 -2 мб.
//setCRCLength(2); // 0 - crc off ,1 - 8bit ,2 - 16bit
//setPALevel(3); // 0...3 -уровень PA.
//setRetries(15,15);

//setAutoAck(0); // отключили автопотверждение

setChannel(25);

openWritingPipe(0xF0F0F0F0D2LL); // Открываем канал передачи
openReadingPipe(1,0xF0F0F0F0E1LL); // Открываем канал приема

clientnf.identifier = chclient;

startListening();
sei();

    DDRC |= _BV(0); //1  /* светодиоды на выход */
    DDRC |= _BV(1); //2

    PORTC |= _BV(0); // 1 /* светодиоды погасить */
    PORTC |= _BV(1); // 2 

for(;;){ // основной цикл программы

 
if ((millis()-time1) >= 1000) {     // обновляем сенсоры раз в секунду (1000млс)
//  тут будут опросы сенсоров

   dhtread ();

              uint8_t crc= (datadht[0] + datadht[1] + datadht[2] + datadht[3]);
	   
	   if (datadht[0]==0 && datadht[1]==0 && datadht[2]==0 && datadht[3]==0) {
	     
	   //обработка ошибки:не подключен датчик !!
	        
	 } else if ( crc == datadht[4]) {
	  
#if nofloat
   	  if (datadht[1]==0 && datadht[3]==0) {
	    // dht11
	    clientnf.temperature_Sensor=datadht[2]*10; // умножение на 10,чтобы было однинаково как у dht22,можно убрать.
	    clientnf.Humidity_Sensor=datadht[0]*10;
	  
	  }else  { // dht22
	     
        clientnf.Humidity_Sensor = (datadht[0] * 256 + datadht[1]);
       clientnf.temperature_Sensor = ((datadht[2] & 0x7F)* 256 + datadht[3]);
       if (datadht[2] & 0x80)  clientnf.temperature_Sensor *= -1;

	}
#else
   	  if (datadht[1]==0 && datadht[3]==0) {
	    // dht11
	    clientnf.temperature_Sensor=datadht[2];
	    clientnf.Humidity_Sensor=datadht[0];
	  
	  }else  { // dht22
	     
        clientnf.Humidity_Sensor = (float)(datadht[0] * 256 + datadht[1])/10;
       clientnf.temperature_Sensor = (float)((datadht[2] & 0x7F)* 256 + datadht[3])/10;
       if (datadht[2] & 0x80)  clientnf.temperature_Sensor *= -1;

	}
#endif	
	 } else {/* обработка ошибки:ошибка CRC */}
  
     time1 = millis();      
  }
 
    //*****************************************************************************************/
   if ((millis() - time2) >= timesend) {
     
if (clientnf.count <= 2147483646) clientnf.count++;      /// счетчик передач для контроля качества канала
else clientnf.count = 0;

  stopListening();
  radiowrite(&clientnf, sizeof(clientnf));
  startListening();
 
  unsigned long started_waiting_at = millis();
  uint8_t timeout = false;
  uint8_t t=0;
    while ( ! available(0) && ! timeout )
    if (millis() - started_waiting_at > timeoutper ) timeout = true;
 
  if ( timeout )
  
 clientnf.Error_Message++;
      
  else {
    radioread( &servernf, sizeof(servernf) );
  }

  if (servernf.identifier == chclient) { // выполнение команд с сервера,если данные предназначены для этого клиента:

// val1= 10 -значит дергаем пинами, val2 - номер пина, val3 - состояние пина
// не забудте установить режим OUTPUT для нужных пинов.
// nRF-USB write 1 10 1 1 1 - что значит установить на 1 выводе порта C логический уровень 1
    if (servernf.val1==10) {
     if (servernf.val3==1) PORTC |= _BV(servernf.val2);
     else PORTC &= ~_BV(servernf.val2);
    }
   
// val1= 11 -значит управляем ШИМ пинами, val2 - номер пина, val3 - уровень 0..255.
// не забудте установить режим OUTPUT для нужных пинов.
// ШИМ возможен только на некоторых пинах !!
 //   if (servernf.val1==11) analogWrite(servernf.val2,servernf.val3);

}

    time2 = millis(); 
    }
    
  }
}


Home`s Smart © 2013-2016. г.Киров.
Цитирование материалов возможно только со ссылкой на сайт. Использование фотоматериалов только с разрешения авторов.