Китайские Arduino Nano

Это Вася. Он потерял пол дня, по тысяче раз перепроверяя код, соединения и пр.пр.пр. А оно всё равно не работало.. Не будьте как Вася (с)

Ну а если подробнее, то развел вот такую простую платку:

Воплотил её в «железе»:

А оно возьми и не заработай при прошивке. Мало того, даже в мониторе порта при выставленном Serial.begin(9600); пишет без крякозябров только на скорости 2400

Убил всё утро на выяснение причины. Оказалось, что у китайского клона свои частоты работы кремния, а потому стандартные казалось бы скетчи где есть привязка к частотам процессора будут или не работать или работать не верно (датчики температуры, дисплеи и т.д.).

Решение: нужно прошивать плату выставив в Arduino IDE верную плату: LGT8F328P Для этого:

  • Запустить Arduino IDE,
  • перейти в Файл/Настройки/
  • В окошко “Дополнительные ссылки…” Вставить https://raw.githubusercontent.com/dbuezas/lgt8fx/master/package_lgt8fx_index.json
  • Нажать ОК
  • Перейти в Инструменты/Плата/Менеджер плат… Начать вводить в поиске “lgt8”. Выбрать и установить LGT8fx Boards
  • Теперь в списке плат Инструменты/Плата/ появится семейство плат Logic Green…
  • Выбираем свою плату

Для более полной совместимости, Clock Divider можно выставить в 2

Компилируем..прошиваем..и всё начинает работать. Внимательнее нужно быть Вася..

Arduino: подключение дисплея ST7735s

Данный дисплей как оказалось с некими особенностями. У части страждущих, после подключения по стандартной схеме с 5в, экран рябит, и покрывается полосами, поэтому приходится подключать его через резисторы в 1кОм, по схеме:

Однако у меня, прокатило и без этого, хотя тоже помучался немножко, но как оказалось просто не пропаял нормально контактную площадку на дисплее. Кроме того, в моём случае необходимо было оставить свободными часть пинов, в том числе 13 и 11, для других устройств, поэтому пришлось переключатся на «софтварную» реализацию функционала MISO/MOSI/SCK. В моём случае схема подключения следующая:

  • vcc — 5v
  • gnd — gnd
  • scl — 8
  • sda — 7
  • res — 5
  • dc — 4
  • cs — 6
  • blk — не используется

Ну и инициализация дисплея следующая соответственно:

#define TFT_SCLK 8
#define TFT_MOSI 7
#define TFT_CS        6
#define TFT_RST       5
#define TFT_DC        4
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

Из минусов — медленная отрисовка на экране. Однако в моём случае это не критично.

Стандартная же схема подключения следующая:

Дисплей на ST7735SArduino
GNDGND
VCC5V
SCL13 (sck)
SDA11 (mosi)
RES9
DC8
CS10 (ss)
BL3.3V

И снова проект на Arduino: подсветка лестницы

Сей проект должен решить задачу подсветки лестницы в темноте при обнаружении движения одним из двух датчиков. Ну бонусом — кнопка принудительного включения и кнопка «новогодних эффектов». Подсветка осуществляется при адресной 5 вольтовой светодиодной ленты, с внешним питанием.

Разработку платы вёл традиционно в веб версии EasyEDA, Принципиальная схема получилась следующая:

А вот тут она-же, но уже в виде текстолитовой однослойной платы, которую вполне можно потравить и самому:

В «железе» пока еще готового варианта нет, детальки едут и Китая и прочих источников, но теоретическую модель в эмуляторе уже можно потрогать тут:

https://wokwi.com/projects/417413301092687873

Код следующий:

#include <Adafruit_NeoPixel.h>
#include <SPI.h>
#include "button.h"
button btn1(9);    // указываем пин кнопки включения/выключения света 
button btn2(12);    // указываем пин кнопки включения/выключения эффектов
boolean button_state; // текущее состояние ленты по кнопке свет вкл/выкл
boolean button_effect; // текущее состояние ленты по кнопке эффектов
#define PIN_PHOTO_SENSOR A0
int pirPin1 = 3;
int pirPin2 = 5;
#define LED_COUNT 16
#define LED_PIN 7

Adafruit_NeoPixel LED_Ring = Adafruit_NeoPixel(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  pinMode(13, OUTPUT);   
  pinMode(pirPin1, INPUT);
  pinMode(pirPin2, INPUT);
  button_state=false;
  LED_Ring.begin(); 
}

void button_press(){
      button_state=!button_state;
      if (button_state==true){
        digitalWrite(13, HIGH);
        for (int i = 0; i < LED_COUNT; i++){
          LED_Ring.setPixelColor(i, LED_Ring.Color(255,255, 0));
          LED_Ring.show();
        };
      } else {
        digitalWrite(13, LOW);
        for (int i = 0; i < LED_COUNT; i++){
          LED_Ring.setPixelColor(i, LED_Ring.Color(0,0, 0));
          LED_Ring.show();
        };        
      };
      delay(1000);
}
// показываем всякие эффекты, пока снова не нажманута любая кнопка
void button_effect_press(){
  int randLed;
  int randR;
  int randG;
  int randB;
  while(true){
    if (btn1.click()) {break;};
    if (btn2.click()) {break;};
    randLed = random(0, LED_COUNT);
    randR = random(0, 255);
    randG = random(0, 255);
    randB = random(0, 255);
    LED_Ring.setPixelColor(randLed, LED_Ring.Color(randR,randG, randB));
    LED_Ring.show();
    delay(100);
  }
}  
void sleep(int ms){
  unsigned long time_old; 
  time_old = millis();
  while(true){
    if (btn1.click()) {button_press();};
    if ((millis()- time_old) >= ms){
      break;
    }
  };
}
void loop() {
  while(true){
    if (btn1.click()) {button_press();}; //нажата кнопка включения-выключения света
    if (btn2.click()) {delay(1000);button_effect_press();}; //нажата кнопка включения-выключения света

    int light_level = analogRead(PIN_PHOTO_SENSOR); // если >300, то считаем что и так светло
    light_level=100; // для отладки - потом убрать!

    int move1 = digitalRead(pirPin1);
    int move2 = digitalRead(pirPin2);
    if ((move1 == HIGH) or (move2 == HIGH)){
      if (button_state==false){  // если свет не включен кнопкой
        if (light_level<250){    // если на леснице темно
          for (int i = 0; i < LED_COUNT; i++){
            if (move1 == HIGH){
              LED_Ring.setPixelColor(i, LED_Ring.Color(255, 0, 0)); // Красный цвет.
            } else {
              LED_Ring.setPixelColor(LED_COUNT-i-1, LED_Ring.Color(255, 0, 0)); // Красный цвет.
            };
            LED_Ring.show();
            sleep(300);
            if (button_state==true){break;};
          };
          if (button_state==false){
            for (int i = 0; i < LED_COUNT; i++){
              LED_Ring.setPixelColor(i, LED_Ring.Color(0, 0, 200));
            };
            LED_Ring.show();
            sleep(6000);
            for (int i = 0; i < LED_COUNT; i++){
              if (move1 == HIGH){
                LED_Ring.setPixelColor(i, LED_Ring.Color(0, 0, 0)); // Красный цвет.
              } else {
                LED_Ring.setPixelColor(LED_COUNT-i-1, LED_Ring.Color(0, 0, 0)); // Красный цвет.
              };
              LED_Ring.show();
              sleep(300);
              if (button_state==true){break;};
            };              
          };
        }
      };
    };
  };

}

Решено: Нужна помощь зала. Не объяснимая ошибка

Прошу очень помощи зала. Ситуация следующая: пишу прошивку «Бортовой компьютер» автомобиля
на основе Arduino Nano (хобби у меня такое, не работа).
Минимальный пример, для воспроизведения ошибки (удалил по максимуму всё, лишь бы ошибка воспроизводилась):

https://wokwi.com/projects/390348182761575425

Проблема в следующем, не обьяснимым образом, теряются данные в переменных при вызове функции translate.

String translate(String txt){
return txt;
};

Например при использовании вот так (строки 141-146):

display.print(translate("Transmission:"));
display.setCursor(0, 20);
display.print(translate("Bridge:"));
display.setCursor(0, 30);
display.print(translate("GRM ribbon:"));
display.display();   

На экран выводится «Bridge». Однако стоит убрать строчку

 display.print(translate("GRM ribbon:"));

Как волшебным образом, на экран начинает выводится и Transmission: и Bridge:.

Дело не только в этой строчке. Закомментировав рандомно часть кода выше-ниже, вообще не относящегося к выводу на экран, можно добиться эффекта, что выводятся на экран все три строчки.

Подумал что памяти не хватает. Но вроде норм. Я уже начинаю сходить с ума, несколько дней бьюсь над проблемой. Проблема воспроизводится и на «реальном железе», не только в эмуляторе.

Update: си не умеет возвращать строки. Только массивы символов. Поэтому верный код что-то вроде:

const char * translate(char *txt){  
  return txt;
};

Arduino: передача массива строк в качестве функции

За что я не очень люблю СИ, так за то что можно споткнуться на пустом месте и долго думать почему так? И в этот раз тоже, долго гуглил, почему у меня не получается передать массив строк в функцию, массив внутри «обнулялся». Наконец наткнулся, что СИ это не умеет. Умеет только передавать указатель на массив. Поэтому функция может выглять подобным образом:


int PutMenu(int cnt,String *mass){
  for (int i=0; i <= cnt; i++){
    Serial.println(mass[i]);    
  };
}

void setup(void){
    Serial.begin(9600);
    String massive[] = { "name", "test", "name", "need", "you", "need", "me", "test" };
    PutMenu(3,massive);
    return 0;
}

void loop(void){

}
1 2 3 4