Lokalny autonomiczny system zbierania danych (część druga)

Początek na tej stronie pod tym linkiem.
Najwygodniejszą metodą pozyskiwania informacji o włączeniu przekaźnika okazała się opcja z optoizolatorami PC817. Schemat zasadniczyLokalny autonomiczny system zbierania danych (część druga)Płytki zawierają po trzy identyczne schematy, wszystko umieszczono w obudowach z tworzywa ABS o wymiarach 100x100 mm. Zdjęcie optoizolatorówLokalny autonomiczny system zbierania danych (część druga) Podczas podłączania do urządzeń startowych z półprzewodnikowymi zaworami, ich prąd upływu jest wystarczający do otwarcia PC817, co spowoduje fałszywe uruchomienie licznika. Aby uniknąć takiej sytuacji proszę dodać jeszcze jeden diodowy element szeregowo do układu diody optoizolatora oraz diody wskazującej działanie. W tym celu należy przerwać zworkę J1 i wlutować dodatkową diodę LED1.
Część odbiorcza wykonana jest na strona 1Lokalny autonomiczny system zbierania danych (część druga)strona 2Lokalny autonomiczny system zbierania danych (część druga)płytce prototypowej podłączanej do ARDUINO MEGA 2560. W tym celu używany jest dwurzędowy złącze na końcu. Jako urządzenie do wyświetlania informacji użyto ekranu z rezystancyjnym dotykiem i czujnikiem temperatury o rozdzielczości 240x400 HX8352B.Lokalny autonomiczny system zbierania danych (część druga) Przy czym złącze do ICSP na płycie ekranu zostało zdemontowane i nie używa gniazda dla karty micro-SD. Rzecz w tym, że 'własne' gniazdo SD nie może być zastosowane z powodu konfliktu na szynie SPI. Do karty flash użyto oddzielnego czytnika kart, który zawiera stabilizator 3,3V oraz buforową mikroskalę z trzema stanami wyjść 74LVS125A. Tu czekały mnie pułapki. Bufor z trzema stanami, ale działał tylko E01-ML01DP5 lub czytnik kart. W komentarzach biblioteki SdFat zauważyłem ostrzeżenie o niekompatybilności z innymi urządzeniami. Zdemontowano konwerter poziomów na TXS0108E i zastąpiono go zworkami, ponieważ E01-ML01DP5 jest tolerancyjny na sygnały 5V - nie pomogło. Za pomocą oscyloskopu wykryto zanik sygnału na linii MISO przy podłączeniu czytnika kart. Po dokładnym zbadaniu stwierdzono, że wejścia sygnału włączającego OE czterech kanałów 74LVS125A były po prostu przylutowane do wspólnego przewodu i nie mogło być mowy o żadnym trzecim stanie. Układ buforowy był używany jako prymitywny konwerter poziomów z 5V do 3.3V przy użyciu rezystorów 3.3 kΩ włączonych szeregowo z liniami sygnałowymi. Oprócz linii MISO. Jej dolny klucz wyjściowy prawdopodobnie przyciągał sygnały do poziomu 'ziemi'. Określając, że sygnał zezwalający linii MISO to pin 13, został on odcięty od ścieżki iprzylutowanyLokalny autonomiczny system zbierania danych (część druga)między wyjściem odczytu (9) 74LVS125A wyboru urządzenia CS a rezystorem dopasowującym. Teraz, jeśli nie ma dostępu do karty pamięci, bufor MISO jest wyłączany i nie przeszkadza w działaniu innego urządzenia.Schemat płytki prototypowejLokalny autonomiczny system zbierania danych (część druga)Odbiornik w pracyLokalny autonomiczny system zbierania danych (część druga)Do podłączenia zegara DS3231 używana jest programowa magistrala I2C (TWI).
Program Arduino IDE// IMPORTANT: Adafruit_TFTLCD LIBRARY MUST BE SPECIFICALLY
// CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD.
// SEE RELEVANT COMMENTS IN Adafruit_TFTLCD.h FOR SETUP.
//by Open-Smart Team and Catalex Team
//catalex_inc@163.com
//Store: dx.com
// open-smart.aliexpress.com/store/1199788
//Demo Function: Display graphics, characters
//Arduino IDE: 1.6.5
// Board: Arduino UNO R3, Arduino Mega2560,Arduino Leonardo

// Board:OPEN-SMART UNO R3 5V / 3.3V, Arduino UNO R3, Arduino Mega2560
//3.2INCH TFT:
// www.aliexpress.com/store/product/3-2-TFT-LCD-Display-module-Touch-Screen-Shield-board-onboard-temperature-sensor-w-Touch-Pen/1199788_32755473754.html?spm=2114.12010615.0.0.bXDdc3
//OPEN-SMART UNO R3 5V / 3.3V:
// www.aliexpress.com/store/product/OPEN-SMART-5V-3-3V-Compatible-UNO-R3-CH340G-ATMEGA328P-Development-Board-with-USB-Cable-for/1199788_32758607490.html?spm=2114.12010615.0.0.ckMTaN

#include <Adafruit_GFX.h> // Core graphics library
//#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#include «SdFat.h» // Use the SdFat library
SdFat SD;
SdFile plik;
Plik myFile;
#define SD_CS_PIN SS

#include <SPI.h> // Подключаем библиотеку для работы с шиной SPI
#include <nRF24L01.h> // Подключаем файл настроек из библиотеки RF24
#include <RF24.h> // Подключаем библиотеку для работы с nRF24L01+
RF24 radio(47, 49);

#include <DS3231.h>

DS3231 rtc(27, 25);
Czas t;

uint16_t r = 6000;
uint32_t k = 0;

volatile unsigned long data;
float leb_1;
float leb_2;
float leb_3;
float leb_4;

uint8_t pipe;
int rc = 0;

uint8_t time_sec_prev;
uint8_t time_day_prev;

//***********************************************//
// If you use OPEN-SMART TFT breakout board //
// Reconmmend you to add 5V-3.3V level converting circuit.
// Of course you can use OPEN-SMART UNO Black version with 5V/3.3V power switch,
// you just need switch to 3.3V.
// The control pins for the LCD can be assigned to any digital or
// analog pins…but we’ll use the analog pins as this allows us to
//—————————————-|
// TFT Breakout — Arduino UNO / Mega2560 / OPEN-SMART UNO Black
// GND — GND
// 3V3 — 3.3V
// CS — A3
// RS — A2
// WR — A1
// RD — A0
// RST — RESET
// LED — GND
// DB0 — 8
// DB1 — 9
// DB2 — 10
// DB3 — 11
// DB4 — 4
// DB5 — 13
// DB6 — 6
// DB7 — 7

// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define GRAY 0x8C51
#define GRAYD 0x39E7

//Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
// If using the shield, all control and data lines are fixed, and
// a simpler declaration can optionally be used:
// Adafruit_TFTLCD tft;
uint16_t g_identifier;

String dataString;
//String numfileMonth =«1.txt»;
char perv [] = {"2.txt"};
//String *numfileMonth=«1.txt» (sizeof (numfileMonth));
///////////////////////////////////////////////////////////////////

void setup(void) {

rtc.begin();

// Для установки времени- раскомментировать нужные строки
// rtc.setDOW(6); // День недели
// rtc.setTime(22, 04, 0); // Время, в формате 24 часа.
// rtc.setDate(4, 5, 2019); // Дата, 29 октября 2018г.

Serial.begin(2000000);
//////// Инициализация экрана
tft.begin(0x65);
tft.reset();
tft.setRotation(0);
tft.cp437(true);
//////////////////Вывод имен, принадлежности оборудования, название организации
tft.fillScreen(BLACK);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.setCursor (8, 0);
tft.println ("DEVELOPERS & BUILD");
tft.setCursor (30, 20);
tft.print (utf8rus("Konstruktor V.V."));
tft.setCursor (40, 40);
tft.print (utf8rus("Tokarz I.I."));
delay (2000);

radio.begin(); // Inicjujemy pracę nRF24L01+
radio.setChannel(120); // Ustalamy kanał odbioru danych (od 0 do 127)
radio.setDataRate (RF24_250KBPS); // Ustalamy szybkość transmisji danych (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS), RF24_1MBPS — 1Mbit/s
radio.setPALevel (RF24_PA_MAX); // Ustalamy moc nadajnika (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
radio.openReadingPipe (1, 0xAABBCCDD11LL); // Otwieramy 1 kanał z identyfikatorem 1 nadajnika 0xAABBCCDD11, do odbioru danych
// Открываем 2 трубу с идентификатором 2 передатчика 0xAABBCCDD22, для приема данных
radio.startListening (); // Włączamy odbiornik, zaczynamy nasłuchiwać otwarte kanały
// radio.stopListening ();
////////Вывод служебной информации
tft.fillScreen(BLACK);
tft.setCursor (8, 0);
tft.setTextSize(1);
////////Начало инициализации SD карты
Serial.println("Initial SD card");
tft.println("Initial SD card");
tft.setCursor (8, 10);
////////Инициализация карты
if (!SD.begin(SD_CS_PIN)) {
Serial.println("initial failed!");
tft.fillRect ( 8, 10, 85, 7, RED);
tft.setTextColor(BLACK);
tft.println("Initial failed!");
return;
}
tft.setTextColor(WHITE);
Serial.println("initialization done");
tft.println("Initialization done");
delay (2000);
////////Считывание времени- даты и присвоение их переменным
t = rtc.getTime();
time_sec_prev = t.sec;
time_day_prev = t.date;
////////Вывод даты принудительно, что б не ждать смены даты для индикации
tft.setCursor ( 180, 0 ); // ustawienie pozycji kursora
tft.fillRect ( 178, 0, 65, 7, GRAY); // czyszczenie obszaru wyświetlania czasu
tft.setTextSize(1);
tft.print(rtc.getDateStr());
////////Вывод названия объектов контроля
tft.setTextSize(2);
tft.setCursor (60, 25);
tft.println (utf8rus("Lebédki I"));
////////Создание файла лога и вывод результата попытки создания
tft.setTextSize(1);
tft.setCursor(130, 10); // jeśli plik loga 2.txt został utworzony, to będzie kontynuowana zapis do pliku
if (SD.exists (perv)) {
//tft.setCursor(0, 90);
tft.println(perv);
Serial.println(perv);
} else {
myFile = SD.open(perv, FILE_WRITE); // jeśli pliku 2.txt nie ma, to on będzie utworzony
myFile.close();
tft.println(perv);
Serial.println(perv);
}
}

void loop(void) {
////////Проверка существования запроса вывода лога в монитор СОМ- порта
if (Serial.available() > 0) {
if (1 == Serial.read());
////////И если принята «1»- то вывод
File myFile = SD.open(perv);
// if the file is available, write to it:
if (myFile) {
while (myFile.available()) {
Serial.write(myFile.read());
}
myFile.close();
}
else {
Serial.println("error opening .txt");
}
}
////////Считывание времени
t = rtc.getTime();
tft.setTextColor(WHITE);
////////Если время изменилось, то вывод новых показаний часов
if ( time_sec_prev != t.sec) {
tft.setCursor ( 120, 0 ); // ustawienie pozycji kursora
tft.fillRect ( 118, 0, 50, 7, GRAY); // czyszczenie obszaru wyświetlania czasu
tft.setTextSize(1);
tft.print(rtc.getTimeStr()); // wyświetlanie wskazań zegara
time_sec_prev = t.sec;
}
////////Если дата изменилась, то вывод новой даты
if ( time_day_prev != t.date) {
tft.setCursor ( 180, 0 ); // ustawienie pozycji kursora
tft.fillRect ( 178, 0, 65, 7, GRAY); // czyszczenie obszaru wyjściowego daty
tft.setTextSize(1);
tft.print(rtc.getDateStr()); // wyświetlanie danych daty
time_day_prev = t.date;
}
////////Если доступен радиоприём, то
if (radio.available(&pipe)) {
////////проверка заполнения буфера приёма,
radio.read(&data, sizeof(data));
////////если доступен нужный адрес передатчика, то
if (pipe == 1) {
////////ждём синхронизирующую последовательность нулей для определения
//начала блока данных
if ( data == 0000 ) {
rc = 0;
} else {
rc ++;
}
////////Запись значений счётчиков и расчёт их в 10 и 100-х долях часа
if ( rc == 1 ) {
leb_1 = data / 3600.0;
}

if ( rc == 2 ) {
leb_2 = data / 3600.0;
}

if ( rc == 3 ) {
leb_3 = data / 3600.0;
}

if ( rc == 4 ) {
leb_4 = data / 3600.0;
}
}
}
r ++;
k ++; // po prostu licznik
//////// С определённой условием периодичностью обновление данных
if ( r >= 6500) {
tft.setTextSize(2);
tft.fillRect ( 0, 41, 180, 64, GRAYD);
Serial.println ("Lebedki I");
tft.setCursor (0, 41);
tft.println (leb_1);
Serial.println (leb_1);
tft.println (leb_2);
Serial.println (leb_2);
tft.println (leb_3);
Serial.println (leb_3);
tft.println (leb_4);
Serial.println (leb_4);
Serial.println (k);
r = 0;
}
////////Запись данных в лог на SD каждые 10 мин.
if ((t.min % 10 == 0) && ( t.sec == 0)) {
tft.setTextSize(1);
tft.setCursor(200, 10);
tft.setTextColor(BLACK);
////////Создание строки в формате .csv
String dataString = String (rtc.getDateStr()) + ", " + (rtc.getTimeStr()) + ", " + (leb_1) + ", " + (leb_2)
+ ", " + (leb_3) + ", " + (leb_4) + ", ";
////////Запись в файл и вывод результатов процесса записи
myFile = SD.open(perv, FILE_WRITE); // jeśli plik o nazwie "2.txt" nie istnieje, zostanie utworzony.
if (myFile) {
myFile.println(dataString);
myFile.close();
tft.fillRect ( 198, 8, 42, 10, GREEN);
tft.println("SD OK");
Serial.println("SD OK");
delay (900); // opóźnienie, w przeciwnym razie rejestruje 13 identycznych odczytów, dopóki sekunda nie upłynie
} else {
tft.fillRect ( 198, 8, 42, 10, RED);
tft.println("SD ERR");
Serial.println("SD ERR");
}
}
}Program do kodowania znaków/* Recode russian fonts from UTF-8 to Windows-1251 */

String utf8rus(String source)
{
int i,k;
String target;
unsigned char n;
char m[2] = { '0', ' ' };

k = source.length(); i = 0;

while (i < k) {
n = source[i]; i++;

if (n >= 0xC0) {
switch (n) {
case 0xD0: {
n = source[i]; i++;
if (n == 0x81) { n = 0xA8; break; }
if (n >= 0x90 && n <= 0xBF) n = n + 0x30; // 0x2F
break;
}
case 0xD1: {
n = source[i]; i++;
if (n == 0x91) { n = 0xB8; break; }
if (n >= 0x80 && n <= 0x8F) n = n + 0x70; // 0x6F
break;
}
}
}
m[0] = n; target = target + String(m);
}
return target;
}Program do kodowania znaków do wyświetlania cyrylicy za pomocą biblioteki Adafruit_GFX powinien być umieszczony w tym samym folderze co główny program. W Adafruit_GFX należy również zamienić plik glcdfont.c na inny czcionkę. Tutaj biblioteka z wymaganą zamianą. Więcej informacji na temat rusyfikacji można łatwo znaleźć w internecie.
Podsumowując, mogę powiedzieć, że system spełnił oczekiwania, łatwiej jest śledzić czas pracy sprzętu. Choć wszystko jest złożone na płytkach prototypowych, nie napotkałem na żadne problemy w ich działaniu. Pierwsze elementy działają już od ponad pół roku i przetrwały zimę. Ostatnia konstrukcja na 9 kontrolowanych agregatach działa od 5 marca i rejestruje czas pracy już oficjalnie.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster