Мусор в Serial monitor

Я пересматриваю свои вещи Arduino (я хочу восстановить Teleinfo Shield, чтобы внимательно следить за моим энергопотреблением). Я просто не могу заставить это работать (Teleinfo Shield + Уно Wi-Fi).

При попытке проверить, что происходит, я получаю вот такие экраны Serial Monitor.

Есть подсказки, как решить? Это происходит и с другими Uno и другими версиями IDE.

Спасибо за любую помощь, ответы, которые я нашел в разных местах, не привели меня к решению.

Я пробовал несколько настроек скорости (каждый раз одно и то же для порта и монитора), и иногда ничего не писалось, иногда полная херня, иногда как показано

Код выглядит следующим образом: Teleinfo_Arduino_V0_3E.ino (просто добавлено несколько строк, записывающих в последовательный порт, чтобы следить за прогрессом; и соответственно изменен Serial.begin и "укорочен", чтобы оставаться в пределах размера, но он отправляет неправильно символы съели начало))

/*
Регистратор данных Téléinfo 2 на базе Arduino

Compteur 1: завершение
Compteur 2: производство solaire en tarif BASE

Июнь 2011:
v0.2 * автоматическое прохождение до конца дня
исправьте ошибку в BBR
запись модификации на SD (использование teleinfoFile.print вместо переменной STRING
который приводит к сбою Arduino с подписками BBR
v0.2a * добавлен режим без полной мощности для старого счетчика и ее расчет для ПО анализа
v0.2b * для Arduino 1.0 (обновление RTC и использование библиотеки SD, поставляемой с 1.0)
v0.2c * изменен тип переменной, чтобы избежать 2 записей в одну минуту (особенно на proc + fast)
v0.3 * автоматическое определение типа подписки на счетчике 1
v0.3a * Функция установки времени через USB (последовательный интерфейс) на скорости 1200 бод, 7-битный контроль четности
Процедура:
1- карта отключена, извлеките батарею из держателя (для сброса часов)
2- снимаем перемычку с телеинфо щита
3- настройте программное обеспечение эмулятора терминала (termite, Hyperterminal...) на скорость 1200 бод, 7 бит, четная четность.
4- включите карту.
-- Программа обнаружит сброс часов и попросит вас ввести время и дату. --

v0.3b * Исправлена ошибка вычисления счетчика PAP 2, счетчика ежедневных записей 2
v0.3c * Три фазы через счетчик 2
v0.3d * исправлена ошибка перевода строки на счетчике 2 (заголовок файла)
v0.3e * Исправлена ошибка при отсутствии счетчика 2
*/

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>

const char version_logiciel[6] = "V0.3e";

// #define echo_USB //отправляем все телеинформационные кадры на USB
#define message_systeme_USB  //отправлять сообщения на USB (инициализация SD, время запуска и эхо-ошибка)

//*************************************************** ** **********************************************
byte inByte = 0;  // входящий символ телеинформации
char buffteleinfo[21] = "";
byte bufflen = 0;
byte mem_sauv_minute = 1;
byte mem_sauv_journee = 1;
byte num_abo = 0;
byte type_mono_tri[2] = { 0, 0 };
uint8_t presence_teleinfo = 0;  // если есть телеинформационный сигнал
byte presence_PAP = 0;          // если PAP присутствует
boolean cpt2_present = true;    // запоминаем наличие счетчика 2
boolean compteursluOK = false;  // разрешить запись значения на SD
boolean mem_affichage_cpt2_present = true;

int ReceptionOctet = 0;            // переменная хранения для байтов, полученных последовательным портом
unsigned int ReceptionNombre = 0;  // переменная для подсчета числа, полученного последовательным портом
byte reg_horloge = 1;
boolean mem_reg_horloge = false;
const uint8_t val_max[6] = { 24, 59, 59, 31, 12, 99 };

// Объявления Teleinfo
unsigned int papp = 0;  // Полная мощность, ВА

uint8_t IINST[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };  // Мгновенная интенсивность Фаза 1, A (мгновенная эффективная интенсивность) или 1 фаза в одной фазе

unsigned long INDEX1 = 0;  // Индекс опции Tempo - Непиковые часы Blue Days, Wh
unsigned long INDEX2 = 0;  // Индекс параметра Tempo - Часы пик Blue Days, Wh
unsigned long INDEX3 = 0;  // Индекс опций Tempo - Непиковые часы Белые дни, Втч
unsigned long INDEX4 = 0;  // Индекс параметра Tempo - Пиковые часы Белые дни, Втч
unsigned long INDEX5 = 0;  // Индекс опции темпа - Непиковые часы Красные дни, Втч
unsigned long INDEX6 = 0;  // Индекс опции темпа - Пиковые часы Red Days, Wh

// счетчик 2 (солнечная энергия настроена в БАЗОВОМ тарифе ERDF)
unsigned long cpt2index = 0;     // Индекс варианта База счетчика выработки солнечной энергии, Втч
unsigned int cpt2puissance = 0;  // Измеритель полной солнечной выработки, ВА

#define debtrame 0x02
#define debligne 0x0A
#define finligne 0x0D

// *************** декларация карты micro SD ******************
const byte chipSelect = 4;

// *************** объявление активации счетчика 1 или 2 ******
#define LEC_CPT1 5  // чтение счетчика 1
#define LEC_CPT2 6  // чтение счетчика 2
//
byte verif_cpt_lu = 0;
//

byte compteur_actif = 1;           // номер считываемого счетчика
byte donnee_ok_cpt[2] = { 0, 0 };  // чтобы проверить, что данные находятся в памяти перед записью в файл
byte donnee_ok_cpt_ph[2] = { 0, 0 };

// **************** Переменные RTC ********************************** *****
byte minute, heure, seconde, jour, mois, jour_semaine;
unsigned int annee;
char date_heure[18];
char mois_jour[7];
byte mem_chg_heure = 0;  //чтобы не ходить постоянно с 3 до 2 ночи в последнее воскресенье октября
RTC_DS1307 RTC;

// ************* инициализация **********************************
void setup() {
  // инициализируем порт 0-1 для чтения Teleinfo
  Serial.begin(1200);
  // четная четность E
  // 7-битные данные
  UCSR0C = B00100100;
#ifdef message_systeme_USB
  Serial.print(F("-- Teleinfo USB Arduino "));
  Serial.print(version_logiciel);
  Serial.println(F(" --"));
#endif
  // инициализация счетчика выбора выходов
  pinMode(LEC_CPT1, OUTPUT);
  pinMode(LEC_CPT2, OUTPUT);
  digitalWrite(LEC_CPT1, HIGH);
  digitalWrite(LEC_CPT2, LOW);

  // проверяем наличие microSD и инициализирована ли она:
#ifdef message_systeme_USB
  if (!SD.begin(chipSelect)) {
    Serial.println(F("> Erreur carte, ou carte absente !"));
    return;
  }
  Serial.println(F("> microSD initialisee !"));
#endif

  // инициализация RTC16

  Wire.begin();
  RTC.begin();

  if (!RTC.isrunning()) {
#ifdef message_systeme_USB
    Serial.println(F("RTC non configure !"));
#endif
  }

  DateTime now = RTC.now();  // лекция часового искусства
  annee = now.year();
  mois = now.month();
  jour = now.day();
  heure = now.hour();
  minute = now.minute();
  jour_semaine = now.dayOfTheWeek();

  format_date_heure();
#ifdef message_systeme_USB
  Serial.println(date_heure);
#endif
}

// **************** основной цикл **********************************

void loop()  // программа цикла
{

  if (!(RTC.isrunning()) && (reg_horloge < 7)) {  // если часы не настроены
    digitalWrite(LEC_CPT1, LOW);

    if (!mem_reg_horloge) {
      switch (reg_horloge) {  // начало структуры
        case 1:
          Serial.print(F("Entrer Heure: "));
          break;
        case 2:
          Serial.print(F("Entrer Minute: "));
          break;
        case 3:
          Serial.print(F("Entrer Seconde: "));
          break;
        case 4:
          Serial.print(F("Entrer Jour: "));
          break;
        case 5:
          Serial.print(F("Entrer Mois: "));
          break;
        case 6:
          Serial.print(F("Entrer Annee 20xx: "));
          break;
      }
      mem_reg_horloge = true;
    }
    if (Serial.available() > 0) {  // если символ в очереди

      Serial.print(F("un nombre a ete recu")); //---- прочитаем полученное число
      while (Serial.available() > 0) {
        // пока буфер не пуст читать все полученные символы за один раз
        inByte = Serial.read();         // возвращает 1-й байт в последовательной очереди (-1, если нет)
        Serial.println(inByte);
        if (((inByte > 47) && (inByte < 58)) || (inByte == 13)) {
          ReceptionOctet = inByte - 48;  // преобразовать значение ASCII в десятичное значение
          if ((ReceptionOctet >= 0) && (ReceptionOctet <= 9)) ReceptionNombre = (ReceptionNombre * 10) + ReceptionOctet;
          // если полученное значение соответствует числу, вычисляем число
          Serial.print(ReceptionNombre);
          Serial.print(reg_horloge);
        } else
          presence_teleinfo = -1;
      }  // конец пока
      if (inByte == 13) {
        if ((ReceptionNombre > val_max[reg_horloge - 1]) || (ReceptionNombre == -1)) {
          Serial.println(F("Erreur horaire"));
          ReceptionNombre = 0;
          mem_reg_horloge = true;
        } else {
          Serial.print("cela bugge");
          switch (reg_horloge) {  // начало структуры
            case 1:
              heure = ReceptionNombre;
              Serial.print("heure:");
              Serial.println(heure);
            case 2:
              minute = ReceptionNombre;
              break;
            case 3:
              seconde = ReceptionNombre;
              break;
            case 4:
              jour = ReceptionNombre;
              break;
            case 5:
              mois = ReceptionNombre;
              break;
            case 6:
              annee = 2000 + ReceptionNombre;
              break;
          }

          mem_reg_horloge = false;
          ReceptionNombre = 0;
          ++reg_horloge;

          if (reg_horloge > 6) {
            RTCsetTime();
            Serial.println(F("Reglage heure OK - installer le cavalier pour la teleinfo"));
            digitalWrite(LEC_CPT1, HIGH);
          }
        }
      }
    }
  }

  else {

    DateTime now = RTC.now();  // считываем часы
    minute = now.minute();
    heure = now.hour();
    seconde = now.second();

    if ((heure == 0) && (minute == 0) && (seconde == 0)) {
      annee = now.year();
      mois = now.month();
      jour = now.day();
      jour_semaine = now.dayOfTheWeek();
    }

    // переход на летнее время +1 час
    // библиотека RTC имеет функцию: dayOfWeek, которая показывает день недели (обо всем позаботится DS1307!)
    // ответ: 0 -> Воскресенье, 1 -> Понедельник и др.
    //
    if ((heure == 2) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 3) && (jour > 24)) {
      heure = 3;
      RTCsetTime();
    }

    // переход на зимнее время -1 час
    if ((heure == 3) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 10) && (jour > 24) && (mem_chg_heure == 0)) {
      heure = 2;
      RTCsetTime();
      mem_chg_heure = 1;
    }

    if ((heure == 23) && (minute == 59) && (seconde == 10))  // чтобы не сбрасывалось при записи каждую минуту
    {
      if ((mem_sauv_journee == 0) && (compteursluOK))  // только одна запись в день!
      {
        fichier_annee();
        mem_sauv_journee = 1;
        mem_chg_heure = 0;
      }
    } else
      mem_sauv_journee = 0;

    if (seconde == 1) {
      if ((mem_sauv_minute == 0) && (compteursluOK))  // только одна запись в минуту!
      {
        enregistre();
        mem_sauv_minute = 1;
      }
    } else
      mem_sauv_minute = 0;

#ifdef message_systeme_USB
    if ((donnee_ok_cpt[1] == B00000111) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 detecte"));
      mem_affichage_cpt2_present = false;
    } else if ((!cpt2_present) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 non present !"));
      mem_affichage_cpt2_present = false;
    }
#endif

    if ((donnee_ok_cpt[0] == verif_cpt_lu) and (cpt2_present)) {
      if ((type_mono_tri[0] == 1) && (donnee_ok_cpt_ph[0] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[0] == 3) && (donnee_ok_cpt_ph[0] == B10000111))
        bascule_compteur();
    } else if ((donnee_ok_cpt[1] == B00000001) or ((compteur_actif == 2) and (!cpt2_present))) {
      if ((type_mono_tri[1] == 1) && (donnee_ok_cpt_ph[1] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[1] == 3) && (donnee_ok_cpt_ph[1] == B10000111))
        bascule_compteur();
      compteursluOK = true;
    }

    if (compteur_actif == 2) {
      if (presence_teleinfo > 200) {
        cpt2_present = false;
        compteursluOK = true;
        bascule_compteur();
      } else
        cpt2_present = true;
    }

    read_teleinfo();
  }
}

////////////////////////////////////////////////// //////////////////
// Вычисление контрольной суммы телеинфо
////////////////////////////////////////////////// //////////////////
char chksum(char *buff, uint8_t len) {
  int i;
  char sum = 0;
  for (i = 1; i < (len - 2); i++) sum = sum + buff[i];
  sum = (sum & 0x3F) + 0x20;
  return (sum);
}

////////////////////////////////////////////////// / ////////////////
// формат даты & время показа или записи
////////////////////////////////////////////////// / ////////////////
void format_mois_jour() {
  sprintf(mois_jour, "%02d,%02d,", mois, jour);
}

// Преобразование обычных десятичных чисел в двоично-десятичные числа
static uint8_t bin2bcd(uint8_t val) {
  return val + 6 * (val / 10);
}

////////////////////////////////////////////////// / ////////////////
// устанавливаем время RTC (DS1307)
////////////////////////////////////////////////// / ////////////////
void RTCsetTime(void) {
  Wire.beginTransmission(104);  // 104 — это адрес устройства DS1307 (0x68)
  Wire.write(bin2bcd(0));       // начинаем с регистра 0

  Wire.write(bin2bcd(seconde));       //Отправляем секунды как BCD
  Wire.write(bin2bcd(minute));        //Отправляем минуты как BCD
  Wire.write(bin2bcd(heure));         //Отправить часы как BCD
  Wire.write(bin2bcd(jour_semaine));  // Доу
  Wire.write(bin2bcd(jour));          //Отправить день как BCD
  Wire.write(bin2bcd(mois));          //Отправить месяц как BCD
  Wire.write(bin2bcd(annee % 1000));  //Отправить год как BCD

  Wire.endTransmission();
}

MacBookPro 2018 под управлением Monterey

Пример вывода на последовательный монитор

, 👍1

Обсуждение

У вас есть правильная скорость передачи данных, установленная в последовательном мониторе? Не могли бы вы показать свой код Arduino?, @chrisl

См. также https://stackoverflow.com/questions/17893792/arduino-garbled-serial-output, @RowanP

Вы имеете в виду [эту вещь] (https://www.cartelectronic.fr/teleinfo-compteur-enedis/11-shield-teleinfo-arduino-3760313520202.html). Если да, то что вы делаете с перемычками?, @timemage

Да. Я делаю, как рекомендуется, с перемычками на этапе настройки (перемычка удалена, батарея удалена и установлена обратно для обнуления часов), но монитор отображает, как показано, и процесс останавливается после ввода значения часа., @jaladuvar


1 ответ


2

Несоответствие четности

Суть вроде бы вот в чем:

Serial.begin(1200);
// четная пара E
// 7-битные данные
UCSR0C = B00100100;

Код изменяет USART для работы с EVEN паритетом и 1 стоповыми битами или 7E1 для краткости. Последовательный монитор Arduino использует более распространенную конфигурацию стопового бита NO четности 1 (8N1). Я провел небольшой тест типа hello world, чтобы убедиться, что тип вывода, который вы получаете на последовательном мониторе, примерно соответствует ожидаемому для этого несоответствия.

Решение

Итак, вам нужно, чтобы они совпадали. Вы можете:

  • Либо удалите/закомментируйте UCSR0C = B00100100;, чтобы использовать обычную конфигурацию 8N1.

  • Или используйте последовательный эмулятор терминала или другое программное обеспечение, способное настроить порт для четности и 1 стоповые биты (7E1).

Кстати, если у вас есть веская причина использовать 7E1, обычным способом сделать это Serial.begin(1200, SERIAL_7E1); Я не знаю, почему они вручную манипулировали аппаратными регистрами, возможно, код предшествовал поддержке этой формы begin() .

Поддержка последовательного монитора

Последовательный монитор среды IDE, как сообщается, способен настроен для чего-то другого, кроме 8N1, через preferences.txt. У меня это не заработало, но я и не пытался так долго. Возможно, я сделаю это снова и обновлю это. Я думаю, что не закрыл все экземпляры IDE. Теперь я проверил, что Serial Monitor может работать в 7E1, внеся следующие изменения в каталог arduino15 preferences.txt:

Старое чтение строки Чтение новой строки
serial.databits=8 serial.databits=7
serial.parity=N serial.parity=E

Тем не менее, вероятно, будет ошибкой скрывать подобные изменения, чтобы потом, когда потребуется 8N1, вызвать много путаницы. Таким образом, эмулятор терминала по-прежнему, вероятно, является лучшим выбором, если вы действительно хотите или нуждаетесь в четности и 1 стоповом бите. На самом деле, я собираюсь поменять свой сейчас, просто чтобы это меня не зацепило. Я бы использовал обычное программное обеспечение эмулятор терминала вместо того, чтобы возиться с ними, но нужно знать, что вы можете используйте Serial Monitor, если вы вынуждены это делать по какой-либо причине.

,

Хороший улов! По поводу «_использовать эмулятор последовательного терминала_»: Действительно, и комментарии к коду, и [мануал шилда](https://www.gotronic.fr/pj-1137.pdf) рекомендуют настроить эмулятор терминала на 1200 /7Е1. Относительно «_возможно, код предшествует поддержке этой формы begin()_»: кажется, что так. Код датирован в комментариях «июнь 2011». Эта форма begin() была [представлена в августе 2012 года](https://github.com/arduino/Arduino/pull/109) и [выпущена в ноябре 2012 года](https://github.com/arduino/ Arduino/релизы/тег/1.0.2)., @Edgar Bonet

О, круто. Спасибо за поиск. Я, наверное, должен был, но из-за всего этого умственного жонглирования формулировками, я думаю, я просто упустил эту мысль. Если я снова отредактирую, я скажу, что вы провели исследование, которое в конечном итоге подтвердило это. Я заметил, что они, похоже, не используют IDE до версии 2.0 на скриншоте, так что... В любом случае я, возможно, скоро почувствую себя обязанным, чтобы, возможно, расширить бит последовательного монитора., @timemage

Я поищу все это и вернусь назад, но время для меня ограничено. Большое спасибо за помощь мне в этом., @jaladuvar

Удаление UCSR0C = B00100100; выбрасывает мусор... Я еще посмотрю на это. Спасибо, @jaladuvar