Ви не увійшли.
https://habr.com/ru/articles/234763/
Музыкальный дверной звонок в стиле Star Wars на Arduino ( Attiny13 )
https://www.oscill.com
На ОЛХ можна найти у продажі такий.
https://www.oscill.com/rus/oscilloscopes.html
USB : посилаємо команду - вімикаємо два ланцюга data in/out з невеликою затримкою вимикаємо + та -.
Якою програмою будете посилати команди ?
jokeer пише:Ніт
Ваші вподобання досить незвичнія сумніваюся, чи існує таке готове рішення. Саморобки повинні існувати.
Готового нет, а программируемое решение?
Так, вподобання незвичні, но сейчас это нужно..
Колись робив улучшайзінг по типу Hunter XCH-1200, поливалку на 12 каналів...
https://driver.top/blog/422159/
Необхідна допомога програміста у програмі на Arduino.
"Залізо" зібране (14-канальний пристрій), працює на 100%. Програма працює, але є недоліки, які необхідно прибрати. тел. 099 707 72 17
очень интересно но ничего не понятно ...
renoshnik пише:String nmeaSentence = ""; // Переменная для хранения NMEA-строки ... nmeaSentence += c; // Добавить символ к строке NMEA ...
Навіщо зберігати символи в String, якщо потім їх копіювати в char[] ?
ось трохи змінив ...
String nmeaSentence = "";
boolean str_read = true;
void setup() { Serial.begin(9600); }
void serialEvent() { nmeaSentence = Serial.readStringUntil('n');
if (nmeaSentence.length() > 0 && str_read) { GPS_run(nmeaSentence); }
}
void loop() {
}
void GPS_run(String nmea) {
str_read = false;
// ********************************************
str_read = true;
}
renoshnik пише:char fullSpeed[5]; sprintf(fullSpeed, "%03d", speedKmh); // чтобы избежать переполнения sprintf(fullSpeed, sizeof(fullSpeed), "%03d", speedKmh);
Така конструкція чомусь виводить на екран якісь сторонні символи замість данних ...
snprintf. Я ж поправився вище.
Взагалі комілятор мав би видати попередження. Чи у вас вони вимкнені?
Вже старий, не додивився ...
char fullSpeed[5];
sprintf(fullSpeed, "%03d", speedKmh);
// чтобы избежать переполнения
sprintf(fullSpeed, sizeof(fullSpeed), "%03d", speedKmh);
Така конструкція чомусь виводить на екран якісь сторонні символи замість данних ...
Працює, не димить, не іскрить - це вже добре
![]()
Але перевірку контрольної суми я б таки додав. Хто зна, що там з UART'у може прийти. Так хоч якась валідація.dimich пише:sprintf(fullSpeed, sizeof(fullSpeed), "%03d", speedKmh);
Звісно ж, тут snprintf. То я при цитуванні забув поправити.
Я вже зробив заготовку, але поки не перевіряв ....
String nmeaSentence = "$GPRMC,123456.00,A,4916.45,N,12311.12,W,0.05,89.60,030615,,,A*1C";
void setup() {
Serial.begin(9600);
if (checkChecksum(nmeaSentence)) {
Serial.println("Контрольная сумма совпадает.");
} else {
Serial.println("Ошибка контрольной суммы.");
}
}
void loop() {
// Основной код программы
}
bool checkChecksum(const String& nmea) {
// Найти индекс символа '*'
int asteriskIndex = nmea.indexOf('*');
if (asteriskIndex == -1 || asteriskIndex < 1) {
return false; // Нет контрольной суммы или неверный формат
}
// Извлечь контрольную сумму из строки (после '*')
String checksumStr = nmea.substring(asteriskIndex + 1);
int expectedChecksum = strtol(checksumStr.c_str(), nullptr, 16);
// Вычислить контрольную сумму
int calculatedChecksum = 0;
for (int i = 1; i < asteriskIndex; i++) { // Пропускаем '$'
calculatedChecksum ^= nmea[i];
}
return calculatedChecksum == expectedChecksum;
}
renoshnik пише:String nmeaSentence = ""; // Переменная для хранения NMEA-строки ... nmeaSentence += c; // Добавить символ к строке NMEA ... char nmeaCStr[nmea.length() + 1]; nmea.toCharArray(nmeaCStr, nmea.length() + 1); ...
Навіщо зберігати символи в String, якщо потім їх копіювати в char[] ?
renoshnik пише:if (fieldIndex == 1) {printFormattedTime(token);token = nullptr;} // выводим время 1 if (fieldIndex == 2) {printFormattedValid(token);token = nullptr;} // выводим валидность координат 2 if (fieldIndex == 7) {printFormattedSpeed(token);token = nullptr;}// выводим скорость 7 if (fieldIndex == 9) {printFormattedDate(token);token = nullptr;} // выводим дату 9 token = commaPos + 1;
Навіщо присвоювати token = nullptr, якщо відразу ж присвоюється token = commaPos + 1?
Раз на то пішло, то хоча бswitch (fieldIndex) { case 1: printFormattedTime(token); break; case 2: printFormattedValid(token); break; case 7: printFormattedSpeed(token); break; case 9: printFormattedDate(token); break; default: break; } token = commaPos + 1;
renoshnik пише:float Kmh = atof(rawKnot) * 1.852; int speedKmh = (int)Kmh;
Якщо вже так хочеться float, навіщо проміжна змінна і C-style кастинг? Такий же результат дасть
int speedKmh = atof(rawKnot) * 1.852;
А краще
int speedKmh = round(atof(rawKnot) * 1.8523);
renoshnik пише:char fullSpeed[5]; sprintf(fullSpeed, "%03d", speedKmh);
У разі невалідних вхідних даних може бути переповнення буфера. Хоча б
sprintf(fullSpeed, sizeof(fullSpeed), "%03d", speedKmh);
Хоча у разі невалідних вхідних даних переповнення буфера буде ще на стадії отримання строки з UART.
1. - Згоден, що додає додатковий крок, але мені так було зручніше працювати з рядками на етапі побудови.
2. - про token = nullptr, то я шукав звідки лізуть деякі баги і забув потім видалити, дійсно то зайве.
3. - дякую виправив
4. - дякую виправив
Якось так ....
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>
#define TFT_CS 10
#define TFT_RST 8 // Or set to -1 and connect to Arduino RESET pin
#define TFT_DC 9
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
#include <SoftwareSerial.h>
#include <string.h>
SoftwareSerial gpsSerial(4, 3); // (RX, TX Arduino)
String nmeaSentence = ""; // Переменная для хранения NMEA-строки
const int timezoneOffset = 3; // Часовой пояс (например, +3 для EEST)
boolean valid = false; // флаг валидности координат
boolean drive = false; // флаг движения
boolean overtime = false; // флаг время/скорость
// char tokenKnot[] = "10.5"; // Пример тестового значения
void setup() {
// Serial.begin(9600);
gpsSerial.begin(9600);
tft.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab
tft.setRotation(3); // Установка ориентации экрана
tft.fillScreen(ST77XX_BLACK); // Установка начального цвета фона
}
void loop() {
while (gpsSerial.available()) {
char c = gpsSerial.read(); // Считать один символ из GPS
if (c == 'n') { // Проверить, является ли символ концом NMEA-строки
GPS_run(nmeaSentence); // Передать строку в GPS_run() для обработки
nmeaSentence = ""; // Очистить строку для следующей NMEA-строки
} else if (c != 'r') { // Игнорировать символ возврата каретки
nmeaSentence += c; // Добавить символ к строке NMEA
}
}
}
void GPS_run(String nmea) {
if (nmea.startsWith("$GPRMC")) { // Проверка на идентификатор строки
// Serial.println("______________________________");
// Serial.println("_______ вход в $GPRMC ***1*** ");
char nmeaCStr[nmea.length() + 1];
nmea.toCharArray(nmeaCStr, nmea.length() + 1);
int fieldIndex = 0;
char *token = nmeaCStr;
char *commaPos = strchr(token, ','); // Найти первую запятую
while (fieldIndex <= 13) {
if (commaPos) {
*commaPos = '