Метеостанция
- Войдите на сайт для отправки комментариев
Пт, 02/06/2017 - 17:06
Здравствуйте. прошу помощи у опытных людей. проблема такая, хочу сделать погодную станцию на ардуино нано и на датчиках: BMP280, MQ135, DHT11, дисплей с I2C 16 на 2.
очень прошу помоч, я ещё совсем новичок и буду благодарен тому кто поможет! И очень прошу скинуть все библиотеки .
Здравствуйте. прошу помощи у опытных людей. проблема такая, хочу сделать погодную станцию на ардуино нано и на датчиках: BMP280, MQ135, DHT11, дисплей с I2C 16 на 2.
очень прошу помоч, я ещё совсем новичок и буду благодарен тому кто поможет! И очень прошу скинуть все библиотеки .
Начните с малого, подключите дисплей и научитесь на нем что-нить писать, примеров море. Как только освоите, начинайте подключать по очереди датчики и пробовать с ними работать - так вы больше поймете. Я конечно, могу скинуть готовый вариант, но предпологаю, у вас появится куча вопросов, а мне еще сад посадить нужно :).
Очень вас прошу как будет время скинуть скетч!заранее спасибо!)
так есть же на форуме
Очень вас прошу как будет время скинуть скетч!заранее спасибо!)
Код состоит из двух частей - приемника и передатчика.
Передатчик и приемник соответственно
/*******************************************************************************************************************/ // Библиотеки для работы с датчиком температуры #include "OneWire.h" #include "DallasTemperature.h" #include "NRF24L01.h" //#include <Wire.h> #include <Adafruit_BMP085.h> #include "DHT.h" /******************************************* Датчик давления BMP180 ************************************************/ Adafruit_BMP085 _mrBMP; /************************************** Датчик влажности AM2302 (AM2302) *******************************************/ #define pinDHT 2 // Подключение датчика влажности к D2 DHT _mrDHT(pinDHT, DHT22); /******************************************** Датчик температуры ***************************************************/ // Выход данных датчика температуры подключен к pin A3 (16) Arduino #define one_wire_bus 16 // Создаем экземпляр класса oneWire, передаевая ему параметр (номер пина Arduino) OneWire oneWire(one_wire_bus); // DallasTemperature sensors(&oneWire); /********************************************************************************************************************/ /****************************************** Функции получения данных ************************************************/ /*******************************************************************************************************************/ // Объединение данных метеостанции двух видов - unsigned char и struct union mrData { unsigned char buf[32]; struct { float temp; int lux; long pressure; int humidity; int wspeed; int wdir; } txData; }; // Создаем экземпляр объединения union mrData _mrData; /*******************************************************************************************************************/ // Функция получения данных с датчиков освещенности и вычисления среднего значения int fnGetLux(void) { return (analogRead(A0) + analogRead(A1))/2; } /*******************************************************************************************************************/ // Функция получения данных с датчиков температуры и вычисления среднего значения float fnGetTemp(void) { sensors.requestTemperatures(); return (sensors.getTempCByIndex(0) + sensors.getTempCByIndex(1))/2; } /*******************************************************************************************************************/ // Функция получения давления с датчика // Сразу переводим в миллиметры ртутного столба // long fnGetPressure(void) { return (_mrBMP.readPressure())/133.322; } /*******************************************************************************************************************/ // Функция получения влажности воздуха int fnGetHumidity(void) { return _mrDHT.readHumidity(); } /*******************************************************************************************************************/ // Функция получения скорости ветра int fnGetWSpeed(void) { return 7; } /*******************************************************************************************************************/ // Функция получения направления ветра int fnGetWDir(void) { return 47; } /*******************************************************************************************************************/ /*******************************************************************************************************************/ /**************************** Переменные и функции для работы с радиомодулем *************************************/ /*******************************************************************************************************************/ #define TX_ADR_WIDTH 5 // 5 unsigned chars TX(RX) address width #define TX_PLOAD_WIDTH 32 // 32 unsigned chars TX payload unsigned char TX_ADDRESS[TX_ADR_WIDTH] = { 0x34,0x43,0x10,0x10,0x01 }; // Define a static TX address unsigned char rx_buf[TX_PLOAD_WIDTH] = {0}; // initialize value unsigned char tx_buf[TX_PLOAD_WIDTH] = {0}; /*******************************************************************************************************************/ // Функция инициализации модуля передатчика void fnIniNRF() { SPI_DIR = ( CE + SCK + CSN + MOSI); SPI_DIR &=~ ( IRQ + MISO); SPI_PORT&=~CE; // chip enable SPI_PORT|=CSN; // Spi disable SPI_PORT&=~SCK; // Spi clock line init high } /*******************************************************************************************************************/ // Функция передачи данных void fnTransmitData() { // Заполняем буфер для передачи данными с датчиков for(int i=0; i<32; i++) { tx_buf[i] = _mrData.buf[i]; } unsigned char status = SPI_Read(STATUS); // read register STATUS's value if(status&TX_DS) // if receive data ready (TX_DS) interrupt { SPI_RW_Reg(FLUSH_TX,0); SPI_Write_Buf(WR_TX_PLOAD,tx_buf,TX_PLOAD_WIDTH); // write playload to TX_FIFO } if(status & MAX_RT) // if receive data ready (MAX_RT) interrupt, this is retransmit than SETUP_RETR { SPI_RW_Reg(FLUSH_TX,0); SPI_Write_Buf(WR_TX_PLOAD,tx_buf,TX_PLOAD_WIDTH); // disable standy-mode } SPI_RW_Reg(WRITE_REG+STATUS,status); // clear RX_DR or TX_DS or MAX_RT interrupt flag delay(1000); } /*******************************************************************************************************************/ //*************************************************** void setup() { // Начало работы с датчиками температуры sensors.begin(); // Запускаем датчик давления _mrBMP.begin(); // Запускаем датчик влажности _mrDHT.begin(); fnIniNRF(); TX_Mode(); // set TX mode } void loop() { // Заполняем структуру значениями, полученными с датчиков _mrData.txData.temp = fnGetTemp(); _mrData.txData.lux = fnGetLux(); _mrData.txData.pressure = fnGetPressure(); _mrData.txData.humidity = fnGetHumidity(); _mrData.txData.wspeed = fnGetWSpeed(); _mrData.txData.wdir = fnGetWDir(); fnTransmitData(); } /************************************************** * Function: SPI_RW(); * * Description: * Writes one unsigned char to nRF24L01, and return the unsigned char read * from nRF24L01 during write, according to SPI protocol **************************************************/ unsigned char SPI_RW(unsigned char Byte) { unsigned char i; for(i=0;i<8;i++) // output 8-bit { if(Byte&0x80) { SPI_PORT |=MOSI; // output 'unsigned char', MSB to MOSI } else { SPI_PORT &=~MOSI; } SPI_PORT|=SCK; // Set SCK high.. Byte <<= 1; // shift next bit into MSB.. if(SPI_IN & MISO) { Byte |= 1; // capture current MISO bit } SPI_PORT&=~SCK; // ..then set SCK low again } return(Byte); // return read unsigned char } /**************************************************/ /************************************************** * Function: SPI_RW_Reg(); * * Description: * Writes value 'value' to register 'reg' /**************************************************/ unsigned char SPI_RW_Reg(unsigned char reg, unsigned char value) { unsigned char status; SPI_PORT&=~CSN; // CSN low, init SPI transaction status = SPI_RW(reg); // select register SPI_RW(value); // ..and write value to it.. SPI_PORT|=CSN; // CSN high again return(status); // return nRF24L01 status unsigned char } /**************************************************/ /************************************************** * Function: SPI_Read(); * * Description: * Read one unsigned char from nRF24L01 register, 'reg' /**************************************************/ unsigned char SPI_Read(unsigned char reg) { unsigned char reg_val; SPI_PORT&=~CSN; // CSN low, initialize SPI communication... SPI_RW(reg); // Select register to read from.. reg_val = SPI_RW(0); // ..then read register value SPI_PORT|=CSN; // CSN high, terminate SPI communication return(reg_val); // return register value } /**************************************************/ /************************************************** * Function: SPI_Read_Buf(); * * Description: * Reads 'unsigned chars' #of unsigned chars from register 'reg' * Typically used to read RX payload, Rx/Tx address /**************************************************/ unsigned char SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes) { unsigned char status,i; SPI_PORT&=~CSN; // Set CSN low, init SPI tranaction status = SPI_RW(reg); // Select register to write to and read status unsigned char for(i=0;i<bytes;i++) { pBuf[i] = SPI_RW(0); // Perform SPI_RW to read unsigned char from nRF24L01 } SPI_PORT|=CSN; // Set CSN high again return(status); // return nRF24L01 status unsigned char } /**************************************************/ /************************************************** * Function: SPI_Write_Buf(); * * Description: * Writes contents of buffer '*pBuf' to nRF24L01 * Typically used to write TX payload, Rx/Tx address /**************************************************/ unsigned char SPI_Write_Buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes) { unsigned char status,i; SPI_PORT&=~CSN; // Set CSN low, init SPI tranaction status = SPI_RW(reg); // Select register to write to and read status unsigned char for(i=0;i<bytes; i++) // then write all unsigned char in buffer(*pBuf) { SPI_RW(*pBuf++); } SPI_PORT|=CSN; // Set CSN high again return(status); // return nRF24L01 status unsigned char } /**************************************************/ /************************************************** * Function: TX_Mode(); * * Description: * This function initializes one nRF24L01 device to * TX mode, set TX address, set RX address for auto.ack, * fill TX payload, select RF channel, datarate & TX pwr. * PWR_UP is set, CRC(2 unsigned chars) is enabled, & PRIM:TX. * * ToDo: One high pulse(>10us) on CE will now send this * packet and expext an acknowledgment from the RX device. **************************************************/ void TX_Mode(void) { SPI_PORT&=~CE; SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // Writes TX_Address to nRF24L01 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0 SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans... SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40 SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // Set PWR_UP bit, enable CRC(2 unsigned chars) & Prim:TX. MAX_RT & TX_DS enabled.. SPI_Write_Buf(WR_TX_PLOAD,tx_buf,TX_PLOAD_WIDTH); SPI_PORT|=CE; } Приемник:/*******************************************************************************************************************/ // // Приемник данных с метеостанции // Версия 04-05-2017 // // Метеостанция передает: // среднюю температуру с двух датчиков температуры DS18B20 // среднюю освещенность с двух фоторезисторов серии GM55 // давление // влажность // // Данные принимаются по радиканалу с помощью модуля nRF24l01+ // Запрос данных с метеостанции по времени (модуль реального времени // Данные для последующего анализа пишутся на SD карту (модуль // Подключена клавиатура 4x4 // /*******************************************************************************************************************/ // // Подключение библиотек #include <Keypad.h> #include "U8glib.h" // Библиотека часов реального времени #include <iarduino_RTC.h> // Библиотека работы с картой SD, аппаратный SPI #include <SD.h> #include <SPI.h> // Библиотеки для работы с радиомодулем NRF24L01, программный SPI, порт A #include "NRF24L01.h" /****************************************** Переменные метеостанции *******************************************/ // char _mrStatus; // Текущее состояние метеоприемника. int _mrHd; // Установка часы десятки int _mrHu; // Установка часы единицы int _mrMd; // Установка минуты десятки int _mrMu; // Установка минуты единицы int _mrSd; // Установка секунды десятки int _mrSu; // Установки секунды единицы int _mrYt; // Установка год тысячи, по умолчанию всегда равно 2 int _mrYh; // Установка год сотни int _mrYd; // Установка год десятки int _mrYu; // Установка год единицы int _mrMnd; // Установка месяц десятки int _mrMnu; // Установка месяц единицы int _mrDd; // Установка дни десятки int _mrDu; // Установка дни единицы unsigned long _timeDelay; // Используется для вычисления времени мигания курсора int _blinkCursor; // Показывать или не показывать курсор int _mrCursorPos; // номер редактируемой цифры в режиме редактирования даты и времени String _dataD; // Дата с датчика реального времени в строковом формате String _dataT; // Время с датчика реального времени в строковом формате unsigned long _blink; // Для мигания светодиодов #define _ledSD 30 // Номер порта, к которому подключен светодиод (будет мигать при записи на SD карту) // Массив координат курсора в режиме (_mrStatus = 'A') редактирования даты и времени int _curPos[12] = {0,12,36,48,72,84,96,108,0,12,36,48}; // Объединение данных метеостанции - буфера обмена buf и структуры rxData union mrData { unsigned char buf[32]; struct { float temp; int lux; long pressure; int humidity; int wspeed; int wdir; } rxData; }; // Создаем экземпляр объединения union mrData _mrData; /*******************************************************************************************************************/ /*******************************************************************************************************************/ // Описание состояний приемника метеостанции // _mrStatus = 0 - обычное состояние (отображение текущего времени, температуры, давления, освещенности, влажности) // _mrStatus = 1 - режим отображения состояния SD карты // /*******************************************************************************************************************/ /************************************************** SD карта *******************************************************/ /*******************************************************************************************************************/ // Переменные для работы с SD // для работы с файлами bool _SDexists; // карта в слоте установлена (_SDexists = true) или нет File _mrFile; // Основной файл для записи данных на карту String _fileName; // для работы с информацией о карте Sd2Card _mrCard; SdVolume _mrVolume; //SdFile _mrRoot; // _write = 0; - запись еще не производилась, _write = 1; - запись уже произведена // переменная необходима при циклической записи int _write; // Номер цифрового пина для управления сигналом cs карты SD #define _csSD 53 File _root; // Файл для подсчета числа файлов и их объема на SD карте File _entry; /*******************************************************************************************************************/ // Массив усредненных данных, считанных с SD карты int _mrSDRead[120][4]; //String _readLine; // Массив символов, прочитанных из файла карты SD char _readLine[] = {}; /**********************************************************************************************************************/ /******************************************** Часы реального времени **************************************************/ /**********************************************************************************************************************/ // Переменная для работы с часами RTC iarduino_RTC _myRTC(RTC_DS3231); void fnIniRTC(void) { _myRTC.begin(); } /*******************************************************************************************************************/ // Начальная настройка метеоприемника /*******************************************************************************************************************/ void fnIniMeteoReceiver() { _mrStatus = '0'; _mrCursorPos = 1; _timeDelay = millis(); _blink = millis(); } /*******************************************************************************************************************/ /************************************************* Клавиатура ******************************************************/ /*******************************************************************************************************************/ // Настройка клавиатуры // const byte ROWS = 4; //four rows const byte COLS = 4; //four columns char _customKey; //define the cymbols on the buttons of the keypads char hexaKeys[ROWS][COLS] = { {'A','3','2','1'}, {'B','6','5','4'}, {'C','9','8','7'}, {'D','#','0','*'} }; byte rowPins[ROWS] = {39,41,43,45}; byte colPins[COLS] = {31,33,35,37}; //Создание экземпляра клавиатуры Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); /*******************************************************************************************************************/ /*************************************************** Функции *******************************************************/ /*******************************************************************************************************************/ // Функция заполняет целочисленные переменные времени и даты с датчика реального времени void fnFillDateTime() { String _temp; _dataD = _myRTC.gettime("d-m-Y"); _dataT = _myRTC.gettime("H-i-s"); // Десятки день _temp = _dataD[0]; _mrDd = _temp.toInt(); // Единицы день _temp = _dataD[1]; _mrDu = _temp.toInt(); // месяц десятки _temp = _dataD[3]; _mrMnd = _temp.toInt(); // месяц единицы _temp = _dataD[4]; _mrMnu = _temp.toInt(); // год тысячи _temp = _dataD[6]; _mrYt = _temp.toInt(); // год сотни _temp = _dataD[7]; _mrYh = _temp.toInt(); // год десятки _temp = _dataD[8]; _mrYd = _temp.toInt(); // год единицы _temp = _dataD[9]; _mrYu = _temp.toInt(); // часы десятки _temp = _dataT[0]; _mrHd = _temp.toInt(); // часы единицы _temp = _dataT[1]; _mrHu = _temp.toInt(); // минуты десятки _temp = _dataT[3]; _mrMd = _temp.toInt(); // минуты единицы _temp = _dataT[4]; _mrMu = _temp.toInt(); // секунды десятки _temp = _dataT[6]; _mrSd = _temp.toInt(); // секунды единицы _temp = _dataT[7]; _mrSu = _temp.toInt(); } /*******************************************************************************************************************/ // Функция возвращает истину, если переданный параметр _number делится на другой параметр _div без остатка /*******************************************************************************************************************/ bool fnRestDiv(int _number, int _div) { float _result; int _whole; int _rest; // Делим входное число на делитель _result = _number/_div; // Вычисляем челую часть результата деления _whole = _result; // Вычисляем остаток от деления _rest = _number - _whole*_div; if(_rest == 0) { return true; } else { return false; } } /*******************************************************************************************************************/ /**************************** Переменные и функции для работы с радиомодулем *************************************/ /*******************************************************************************************************************/ #define TX_ADR_WIDTH 5 // 5 unsigned chars TX(RX) address width #define TX_PLOAD_WIDTH 32 // 32 unsigned chars TX payload unsigned char rx_buf[TX_PLOAD_WIDTH]; unsigned char tx_buf[TX_PLOAD_WIDTH]; unsigned char _NRFStatus; unsigned char TX_ADDRESS[TX_ADR_WIDTH] = { 0x34,0x43,0x10,0x10,0x01 }; // Define a static TX address // Инициализация радиомодуля //************************************************** // // Description: // flash led one time,chip enable(ready to TX or RX Mode), // Spi disable,Spi clock line init high //************************************************** void fnIniNRF() { SPI_DIR = ( CE + SCK + CSN + MOSI); SPI_DIR &=~ ( IRQ + MISO); SPI_PORT&=~CE; // chip enable SPI_PORT|=CSN; // Spi disable SPI_PORT&=~SCK; // Spi clock line init high } /***************************************************************************************************************************/ /***************************************************************************************************************************/ /* * Function: SPI_RW(); * * Description: * Writes one unsigned char to nRF24L01, and return the unsigned char read * from nRF24L01 during write, according to SPI protocol **************************************************/ unsigned char SPI_RW(unsigned char Byte) { unsigned char i; for(i=0;i<8;i++) // output 8-bit { if(Byte&0x80) { SPI_PORT |=MOSI; // output 'unsigned char', MSB to MOSI } else { SPI_PORT &=~MOSI; } SPI_PORT|=SCK; // Set SCK high.. Byte <<= 1; // shift next bit into MSB.. if(SPI_IN & MISO) { Byte |= 1; // capture current MISO bit } SPI_PORT&=~SCK; // ..then set SCK low again } return(Byte); // return read unsigned char } /***************************************************************************************************************************/ /***************************************************************************************************************************/ /************************************************** * Function: SPI_RW_Reg(); * * Description: * Writes value 'value' to register 'reg' /**************************************************/ unsigned char SPI_RW_Reg(unsigned char reg, unsigned char value) { unsigned char status; SPI_PORT&=~CSN; // CSN low, init SPI transaction status = SPI_RW(reg); // select register SPI_RW(value); // ..and write value to it.. SPI_PORT|=CSN; // CSN high again return(status); // return nRF24L01 status unsigned char } /***************************************************************************************************************************/ /***************************************************************************************************************************/ /* * Function: SPI_Read(); * * Description: * Read one unsigned char from nRF24L01 register, 'reg' /***************************************************************************************************************************/ unsigned char SPI_Read(unsigned char reg) { unsigned char reg_val; SPI_PORT&=~CSN; // CSN low, initialize SPI communication... SPI_RW(reg); // Select register to read from.. reg_val = SPI_RW(0); // ..then read register value SPI_PORT|=CSN; // CSN high, terminate SPI communication return(reg_val); // return register value } /***************************************************************************************************************************/ /***************************************************************************************************************************/ /* * Function: SPI_Read_Buf(); * * Description: * Reads 'unsigned chars' #of unsigned chars from register 'reg' * Typically used to read RX payload, Rx/Tx address ***************************************************************************************************************************/ /***************************************************************************************************************************/ unsigned char SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes) { unsigned char status,i; SPI_PORT&=~CSN; // Set CSN low, init SPI tranaction status = SPI_RW(reg); // Select register to write to and read status unsigned char for(i=0;i<bytes;i++) { pBuf[i] = SPI_RW(0); // Perform SPI_RW to read unsigned char from nRF24L01 } SPI_PORT|=CSN; // Set CSN high again return(status); // return nRF24L01 status unsigned char } /***************************************************************************************************************************/ /***************************************************************************************************************************/ /* * Function: SPI_Write_Buf(); * * Description: * Writes contents of buffer '*pBuf' to nRF24L01 * Typically used to write TX payload, Rx/Tx address /**************************************************/ unsigned char SPI_Write_Buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes) { unsigned char status,i; SPI_PORT&=~CSN; // Set CSN low, init SPI tranaction status = SPI_RW(reg); // Select register to write to and read status unsigned char for(i=0;i<bytes; i++) // then write all unsigned char in buffer(*pBuf) { SPI_RW(*pBuf++); } SPI_PORT|=CSN; // Set CSN high again return(status); // return nRF24L01 status unsigned char } /***************************************************************************************************************************/ /***************************************************************************************************************************/ /* * Function: RX_Mode(); * * Description: * This function initializes one nRF24L01 device to * RX Mode, set RX address, writes RX payload width, * select RF channel, datarate & LNA HCURR. * After init, CE is toggled high, which means that * this device is now ready to receive a datapacket. /***************************************************************************************************************************/ void RX_Mode(void) { SPI_PORT&=~CE; SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // Use the same address on the RX device as the TX device SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0 SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40 SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // Select same RX payload width as TX Payload width SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // Set PWR_UP bit, enable CRC(2 unsigned chars) & Prim:RX. RX_DR enabled.. SPI_PORT|=CE; // Set CE pin high to enable RX device // This device is now ready to receive one packet of 16 unsigned chars payload from a TX device sending to address // '3443101001', with auto acknowledgment, retransmit count of 10, RF channel 40 and datarate = 2Mbps. } /***************************************************************************************************************************/ /***************************************************************************************************************************/ // Функция приема данных с приемника void fnReadMRData() { // Проверяем статус приемника (передатчика) _NRFStatus = SPI_Read(STATUS); if(_NRFStatus & RX_DR) { SPI_Read_Buf(RD_RX_PLOAD, rx_buf, TX_PLOAD_WIDTH); // read playload to rx_buf SPI_RW_Reg(FLUSH_RX,0); // clear RX_FIFO // В цикле заполняем объединение for(int j = 0; j < 32; j++) { _mrData.buf[j] = rx_buf[j]; } } SPI_RW_Reg(WRITE_REG+STATUS,_NRFStatus); } /**************************************************** Индикатор 7920 *******************************************************/ // Подключение индикатора по SPI U8GLIB_ST7920_128X64_4X u8g(3, 4, 5); /*******************************************************************************************************************/ // Функция вычисляет положение и рисует линию курсора (две полоски под цифрой, номер которой равен numDigit) // Передаваемые параметры: // numDigit - номер редактируемой цифры. Всего редактируемых цифр - 14. // Из них первые 8 относятся к дате, а с 9 по 12 относятся ко времени // void fnDrawCursor(int numDigit, int cursorShow) { // Координаты курсора на мониторе int x; int y; x = _curPos[numDigit - 1]; if(numDigit <=8) { y = 34; } else { y = 58; } if(cursorShow == 1) { u8g.drawHLine(x,y,10); u8g.drawHLine(x,y+1,10); } } /****************************************** Функции вывода информации ******************************************************/ /****************************************** Функции вывода температуры *****************************************************/ void fnShowTemp(void) { // рисуем разделительную полоску u8g.setFont(u8g_font_profont11); u8g.drawStr(30, 8, "temperature"); u8g.drawLine(2,11,125,11); // устанавливаем крупный шрифт u8g.setFont(u8g_font_profont22); // выводим температуру снаружи u8g.drawStr(1, 32, "tO:"); u8g.setPrintPos(40,32); u8g.print(_mrData.rxData.temp); // выводим температуру в помещении u8g.drawStr(1, 56, "tI:"); u8g.setPrintPos(40,56); u8g.print(_mrData.rxData.temp); } /****************************************** Функции вывода давления *****************************************************/ void fnShowPress(void) { // рисуем разделительную полоску u8g.setFont(u8g_font_profont11); u8g.drawStr(36, 8, "pressure"); u8g.drawLine(2,11,125,11); // устанавливаем крупный шрифт u8g.setFont(u8g_font_profont22); u8g.drawStr(1, 32, "Pres:"); u8g.setPrintPos(62,32); u8g.print(_mrData.rxData.pressure); u8g.setPrintPos(100,32); u8g.print("mm"); } /**************************************** Функции вывода освещенности ****************************************************/ void fnShowLux(void) { // рисуем разделительную полоску u8g.setFont(u8g_font_profont11); u8g.drawStr(30, 8, "illumination"); u8g.drawLine(2,11,125,11); // устанавливаем крупный шрифт u8g.setFont(u8g_font_profont22); u8g.drawStr(1, 32, "Illum:"); u8g.setPrintPos(74,32); u8g.print(_mrData.rxData.lux); } /****************************************** Функции вывода влажности ****************************************************/ void fnShowHumidity(void) { // рисуем разделительную полоску u8g.setFont(u8g_font_profont11); u8g.drawStr(34, 8, "humidity"); u8g.drawLine(2,11,125,11); // устанавливаем крупный шрифт u8g.setFont(u8g_font_profont22); u8g.drawStr(1, 32, "humid:"); u8g.setPrintPos(74,32); u8g.print(_mrData.rxData.humidity); } /****************************************** Функции работы с картой SD ***************************************************/ // Получение информации о состоянии SD карты void fnInfoSD(void) { // устанавливаем шрифт u8g.setFont(u8g_font_profont11); // выводим шапку u8g.drawStr(30, 8, "SD-card info"); // рисуем разделительную полоску u8g.drawLine(2,11,125,11); if(_SDexists) { switch (_mrCard.type()) { case SD_CARD_TYPE_SD1: u8g.drawStr(1, 22, "SD type: SD1"); break; case SD_CARD_TYPE_SD2: u8g.drawStr(1, 22, "SD type: SD2"); break; case SD_CARD_TYPE_SDHC: u8g.drawStr(1, 22, "SD type: SDHC"); break; default: u8g.drawStr(1, 22, "SD type: unknown"); } if(!_mrVolume.init(_mrCard)) { u8g.drawStr(1, 22, "Could not find partition"); } u8g.drawStr(1, 33, "FAT type: "); uint32_t _vs = _mrVolume.blocksPerCluster(); _vs *= _mrVolume.clusterCount(); _vs /= 1024; _vs /= 1024; _vs *= 512; String _sdSize = String(_vs, DEC); u8g.setPrintPos(58, 33); u8g.print(_vs); u8g.drawStr(1, 45, "total files: "); u8g.setPrintPos(76, 45); //u8g.print(fnFileNumSD(0)); u8g.print(fnFileNumLines("10-05-17.txt")); } else { u8g.drawStr(8, 24, "--- no SD card ---"); } } /************************************************************************************************************************/ // Функция создает на SD карте файл с именем формата dd-mm-YY.txt // Данные берутся с часов реального времени, т.е. (_myRTC.gettime("d-m-Y") // Сначала сравниваем текущее имя файла с текущей датой // void fnCreateFile() { String _Y = _myRTC.gettime("Y"); String _dm = _myRTC.gettime("d-m"); _fileName = _dm + "-" + _Y[2] + _Y[3] + ".txt"; if(_SDexists) { // Проверяем, если файла с таким именем нет, то создаем его if(!SD.exists(_fileName)) { _mrFile = SD.open(_fileName,FILE_WRITE); _mrFile.close(); } } } /***********************************************************************************************************************/ // Запись метео-информации на SD // Запись производим каждые 10 минут (_m == 0) // Каждый раз проверяем, если был переход на новую дату, то формируем новый файл с новым именем и пишем уже в него // void fnWriteSD() { String _s; // Строка содержит текущие минуты // Запись производим только тогда, когда число минут кратно 10 // Переменной _s присваиваем значение минут текущего времени и преобразуем это значение в целое _s = _myRTC.gettime("i"); int j; j = _s.toInt(); if(_SDexists) // Если карта вставлена, пишем в файл данные с метеостанции { // Если число минут кратно 10 (5) и запись еще не производилась (_write == 0), то начинаем запись if(fnRestDiv(j,5) && _write == 0) { _mrFile = SD.open(_fileName, FILE_WRITE); if(_mrFile) { _mrFile.print(_myRTC.gettime("d-m-Y")); _mrFile.print("/"); _mrFile.print(_myRTC.gettime("H:i:s")); _mrFile.print("/"); _mrFile.print(_mrData.rxData.temp); _mrFile.print("/"); _mrFile.print(_mrData.rxData.lux); _mrFile.print("/"); _mrFile.print(_mrData.rxData.pressure); _mrFile.print("/"); _mrFile.print(_mrData.rxData.humidity); _mrFile.print("/"); _mrFile.print(_mrData.rxData.wspeed); _mrFile.print("/"); _mrFile.print(_mrData.rxData.wdir); _mrFile.println(); _mrFile.close(); } // Записали, устанавливаем флаг, что запись уже была (_write = 1) _write = 1; } // Сбрасываем признак произведенной записи if(!fnRestDiv(j,5)) { _write = 0; _mrFile.close(); } } } /*******************************************************************************************************************/ /************************* Функция считывает заданное значение из файла с SD карты *********************************/ // void fnReadSD(int par) { } /*******************************************************************************************************************/ /*********************** Функция подсчитывает число строк в заданном файле на карте SD *****************************/ // int fnFileNumLines(String _fName) { unsigned char _ch; int i = 0; // Открываем текущий файл _mrFile = SD.open(_fName); // Если файл удачно открыт, начинаем его побайтно читать if(_mrFile) { // Читаем до конца файла while(_mrFile.available()) { _ch = _mrFile.read(); // Если встречаем перевод строки, то увеличиваем i на единицу if(_ch == 0x0D) { i++; } } } _mrFile.close(); return i; } /*******************************************************************************************************************/ /************************ Функция подсчитывает число файлов на карте SD и их суммарный объем **********************/ // p = 0; - возвращает число файлов // p = 1; - возвращает суммарный объем файлов // Переменные _root и _entry объявлены как глобальные // long fnFileNumSD(int p) { // пока игнорируем параметр p int i = 0; long _size = 0; // Перемещение в корневую директорию выполнено в setup // _root = SD.open("/"); // Перемещаемся к первому файлу _entry = _root.openNextFile(); while(true) { _entry = _root.openNextFile(); i++; if(!_entry) { break; } /* Serial.print("file name = "); Serial.println(_entry.name()); Serial.print("file size = "); Serial.println(_entry.size()); */ _size = _size + _entry.size(); /* Serial.print("i = "); Serial.println(i); */ /* Serial.print("_size = "); Serial.println(_size); */ } // _root.close(); // _entry.close(); // Снова вроде перемещаемся в корень _root = SD.open("/"); return _size; } /*******************************************************************************************************************/ // Инициализация карты // void fnIniSD(void) { // Проверяем наличие карты // используется pin 53 Arduino-Mega сигнала CS карты if (!_mrCard.init(SPI_HALF_SPEED, _csSD)) { _SDexists = false; } else { _SDexists = true; SD.begin(_csSD); } } /***********************************************************************************************************************/ /************************************ Основная функция вывода на экран *************************************************/ /***********************************************************************************************************************/ // Основная Функция вывода на экран информации // // Передаваемые параметры: // status - статус метеоприемника, режим вывода информации на монитор // cursorPos - позиция курсора // digitToCorr - новое значение корректируемого параметра // status = 0; основной режим работы, выводим мелким шрифтом дату, время, температуру, освещенность, давление, влажность // status = 1; вывод информации о SD карты // status = 9; режим установки даты и времени (нажатие кнопки 9 на клавиатуре) // void fnShowData(char status, int cursorPos, int digitToCorr) { switch(status) { // Основной режим: выводим дату, время, температуру, освещенность, давление, влажность case '0': // устанавливаем шрифт u8g.setFont(u8g_font_profont11); // выводим дату u8g.drawStr(4, 9, _myRTC.gettime("d-m-Y")); // выводим время u8g.drawStr(76, 9, _myRTC.gettime("H:i:s")); // рисуем разделительную полоску u8g.drawLine(2,11,125,11); // далее выводим показания датчиков u8g.setFont(u8g_font_profont11); u8g.drawStr(0, 22, "temp:"); u8g.setPrintPos(32, 22); u8g.print(_mrData.rxData.temp); u8g.drawStr(0, 34, "lumen:"); u8g.setPrintPos(38, 34); u8g.print(_mrData.rxData.lux); u8g.drawStr(0, 58, "humi:"); u8g.setPrintPos(38, 58); u8g.print(_mrData.rxData.humidity); u8g.drawStr(0, 46, "press:"); u8g.setPrintPos(38, 46); u8g.print(_mrData.rxData.pressure); if(_SDexists) { u8g.drawStr(64, 58, "SD present"); } else { u8g.drawStr(64, 58, "no SD"); } break; // Выводим информацию о SD карте case '1': fnInfoSD(); break; case '2': fnShowTemp(); break; case '3': fnShowPress(); break; case '4': fnShowLux(); break; case '5': fnShowHumidity(); break; case '6': break; // статус равен 'A', выводим дату и время для их редактирования case 'A': u8g.setFont(u8g_font_profont11); u8g.drawStr( 1, 8, "date and time setting"); u8g.drawLine(2,11,125,11); u8g.setFont(u8g_font_profont22); u8g.drawStr( 0, 32, _myRTC.gettime("d-m-Y")); u8g.drawStr( 0, 56, _myRTC.gettime("H:i:s")); fnDrawCursor(cursorPos, _blinkCursor); break; } } /*******************************************************************************************************************/ /*******************************************************************************************************************/ // Начальные установки void setup() { Serial.begin(9600); _mrStatus = '0'; fnIniRTC(); fnIniSD(); _root = SD.open("/"); fnIniNRF(); RX_Mode(); pinMode(_ledSD,OUTPUT); } /*******************************************************************************************************************/ // Основной цикл программы // 1. Считываем символ нажатой клаваши // 2. В зависимости от статуса метеоприемника выполняем определенные действия // // void loop() { // Тестовая запись в порт // Serial.println("987654321quir"); /*******************************************************************************************************************/ // Здесь мы должны запрашивать данные с метеостанции и заполнять соответствующие переменные fnReadMRData(); /*******************************************************************************************************************/ // Здесь мы должны создать файл с заданным именем и записать на карту SD полученные с метеостанции данные fnCreateFile(); fnWriteSD(); /*******************************************************************************************************************/ /*******************************************************************************************************************/ // В основном цикле постоянно считываем код нажатой клавиши _customKey = customKeypad.getKey(); switch(_customKey) { // Если нажата клавиша "С", то независимо от статуса, переходим в статус 0 case 'C': _mrStatus = '0'; break; // Если нажата клавиша 'A', то независимо от режима, переходим в режим коррекции времени case 'A': _mrStatus = 'A'; _mrCursorPos = 1; // Заполняем переменные текущим времением и датой fnFillDateTime(); break; case '0': if(_mrStatus != 'A') { _mrStatus = '0'; } break; case '1': if(_mrStatus != 'A') { _mrStatus = '1'; } break; case '2': if(_mrStatus != 'A') { _mrStatus = '2'; } break; case '3': if(_mrStatus != 'A') { _mrStatus = '3'; } break; case '4': if(_mrStatus != 'A') { _mrStatus = '4'; } break; case '5': if(_mrStatus != 'A') { _mrStatus = '5'; } break; case '6': if(_mrStatus != 'A') { _mrStatus = '6'; } break; case '7': if(_mrStatus != 'A') { _mrStatus = '7'; } break; case '8': if(_mrStatus != 'A') { _mrStatus = '8'; } break; case '9': if(_mrStatus != 'A') { _mrStatus = '9'; } break; } // Если статус равен 'A' (коррекция даты и времени), то в зависимости от нажатой клавиши if(_mrStatus == 'A') { // Если в состоянии коррекции времени нажата цифровая клавиша, то присваеваем новой значение переменной заданной позиции курсора, // и сразу заносим данные в часы реального времени if(isDigit(_customKey)) { switch(_mrCursorPos) { case 1: _mrDd = _customKey - 48; break; case 2: _mrDu = _customKey - 48; break; case 3: _mrMnd = _customKey - 48; break; case 4: _mrMnu = _customKey - 48; break; case 5: _mrYt = _customKey - 48; break; case 6: _mrYh = _customKey - 48; break; case 7: _mrYd = _customKey - 48; break; case 8: _mrYu = _customKey - 48; break; case 9: _mrHd = _customKey - 48; break; case 10: _mrHu = _customKey - 48; break; case 11: _mrMd = _customKey - 48; break; case 12: _mrMu = _customKey - 48; break; } // Заносим в часы новое значение даты и времени (если были изменения, т.е. была нажата цифровая клавиша) _myRTC.settime(0,_mrMd*10+_mrMu, _mrHd*10+_mrHu, _mrDd*10+_mrDu, _mrMnd*10+_mrMnu, _mrYd*10+_mrYu); } // Если нажаты клавиши * или #, то перемещаем курсор // Двигаемся "назад" switch(_customKey) { case '*': if(_mrCursorPos == 1) { _mrCursorPos = 12; } else { _mrCursorPos --; } break; // Двигаемся вперед case '#': if(_mrCursorPos == 12) { _mrCursorPos = 1; } else { _mrCursorPos ++; } } } /*****************************************************************************************************************************/ u8g.firstPage(); do { fnShowData(_mrStatus, _mrCursorPos, 0); } while( u8g.nextPage() ); /*****************************************************************************************************************************/ // Чтобы показать мигающий курсор, вычисляем промежуток времени для получения интервала в 0.75 сек // Если с момента _timeDelay = milis() прошло более 0.75 сек, то включаем курсор (в режиме установки даты и времени) // и "обнуляем" временный промежуток // Если прошло менее 0.75 сек, то просто выключаем курсор if(millis() - _timeDelay > 750) { _timeDelay = millis(); _blinkCursor = 0; digitalWrite(_ledSD,LOW); } else { if(millis() - _timeDelay < 350) { _blinkCursor = 0; } else { _blinkCursor = 1; digitalWrite(_ledSD,HIGH); } } }так есть же на форуме
Ну где ж вы раньше были!? :)
так есть же на форуме
Ну где ж вы раньше были!? :)
Да код для генератора пытался править, есть глюк при переходе из ручного в автоматический режим