STM32 Arduino IDE и дисплей 1602

pixel28
Offline
Зарегистрирован: 23.11.2015

Всем привет! Имеется стандартная синяя плата на STM32. В нее был успешно записан ардуиновский бутлоадер. Теперь я могу спокойно прошиваться по USB. Blink заработал вообще без проблем. Решил сразу подключить дисплей 1602 со стандартной библиотекой. Прописал новые выводы, вгрузил. Но дисплей к сожалению показывает рандомные символы, но иногда проскакивает пара-тройка букв из слов, которые должны выводиться. 
Перепробовал много всего, разные версии ардуины, разные библиотеки, другие порты, другие дисплеи но результат един.
 

Частично помогло только изменение CPU SPEED во вкладке Инструменты. Раньше стояло 72мгц, я же поставил 48мгц.  Теперь при включении на первые секунды слова выводятся правильно, но все равно иногда некорректно, в первой строчке "Interfacing LCD", во второй -CircuitDigest после этого дисплей затягивает каракулями и на этом все. 

Пример кода:
 


#include <LiquidCrystal.h> // include the LCD library

const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; //mention the pin names to with LCD is connected to 
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //Initialize the LCD

void setup() {
  lcd.begin(16, 2);//We are using a 16*2 LCD
  lcd.setCursor(0, 0); //At first row first column 
  lcd.print("Interfacing LCD"); //Print this
  lcd.setCursor(0, 1); //At secound row first column 
  lcd.print("-CircuitDigest"); //Print this
  
  delay(2000); //wait for two secounds 
  lcd.clear(); //Clear the screen
}

void loop() {

  lcd.setCursor(0, 0); //At first row first column 
  lcd.print("STM32 -Blue Pill"); //Print this

  lcd.setCursor(0, 1); //At secound row first column 
  lcd.print(millis() / 1000); //Print the value of secounds
}

 

nik182
Offline
Зарегистрирован: 04.05.2015

А если после lcd.begin и lcd.clear задержки на 2 секунды поставить что будет?

pixel28
Offline
Зарегистрирован: 23.11.2015

Ничего хорошего, к сожалению не получилось. На частоте 72мгц вообще глухо, на 42 реакция такая-же, только теперь с задержками в 2с. 

nik182
Offline
Зарегистрирован: 04.05.2015

А с другими ардуинами этот дисплей пробовали? У меня есть дисплеи которые clear выполняют больше секунды и setCursor 200 мс. Если раньше подать другую команду раньше, то дисплей перестаёт нормально отображать. Но ещё бы я проверил линию Е тестером.

 

pixel28
Offline
Зарегистрирован: 23.11.2015

У меня есть много дисплеев 1602, даже от факса где-то валяется. Сейчас использую качественный дисплей DV16230, с ним проблем на ардуине никаких не было. Пробовал и китайские с али, не работают. 
Не знаю, может загрузчик не тот, но если блинк работает, то и это тоже должно

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

pixel28, а как вы включили дисплей? То, что он 5-вольтовый, а МК 3х вольтовый учли?

pixel28
Offline
Зарегистрирован: 23.11.2015

Подключал как и обычно, сам дисплей к 5ти вольтам. Выводы D7-D4, RS, EN к STM32. Попробовал даже подтянуть эти выводы к 5ти вольтам, ничего не изменилось. Как будто дисплей просто не успевает за STM32...

Помно, когда изучал Ассемблер и мк 8051 была проблема с 1602, потому что мк был слишком скоростной. Какими-то костылями и задержками удалось это исправить 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Посмотрите в библиотеку. Как там сделаны задержки при инициализации. Наверняка дело в них. Если nop-ами, то понятно, что в них. Сделайте нормальные задержки и жизнь наладится.

nik182
Offline
Зарегистрирован: 04.05.2015
void LiquidCrystal::pulseEnable(void) {
  digitalWrite(_enable_pin, LOW);
  delayMicroseconds(1);    
  digitalWrite(_enable_pin, HIGH);
  delayMicroseconds(1);    // enable pulse must be >450ns
  digitalWrite(_enable_pin, LOW);
  delayMicroseconds(100);   // commands need > 37us to settle
} 

Из стандартной библиотеки. Задержки через честные п.п. С этой библиотекой точно должно работать. 

pixel28
Offline
Зарегистрирован: 23.11.2015

Да, задержки во всех библиотеках, которые я пробовал были сделаны именно так. Сегодня попробовал очередную библиотеку  LiquidCrystal, с моим кодом дисплей спокойно завелся на частоте 72мгц, но после отработки Lcd.clear(); появляются кракозябры и дисплей больше не работает. Кажется я понял в чем была вся проблема) Не правильная работа Lcd.clear();  
В итоге заменил все Lcd.clear(); на что-то типа lcd.print("                        "); Отдельно для первой и второй строки и о чудо - работает! 
Но почему же тогда Lcd.clear отказывается работать только у меня:?? У всех остальных она спокойно отрабатывает на STM32. Да, понимаю, что Arduino IDE на STM32 это полнейший бред, но я перешел на STM32 только из-за хорошего АЦП и ЦАП, буду осваивать их и хочу получить точность измерения напряжения в 3 знака после запятой. 

Вот мой код:

#include <LiquidCrystal.h>
 
int sensorPin = PA0;    // к пину Analog IN 0
int sensor2Pin = PA2;   // к пину Analog IN 2
int ledPin = PC13;      // пин к затвору транзистора
 
LiquidCrystal lcd(PB9, PB8, PB7, PB6, PB5, PB4); // initialize the library with the numbers of the interface pins
 
int sensorValue = 0;  // variable to store the value coming from the sensor 
int sensor2Value = 0;  // variable to store the value coming from the sensor 
float LiMinThreshold = 2700; // Lithium Minimal Voltage for load removal
float LiMaxThreshold = 4200; // Lithium Max Voltage for load removal
float NmhMinThreshold = 950; // NMH Minimal Voltage for load removal
float NmhMaxThreshold = 1600; // NMH Max Voltage for load removal
float SelectedMinThreshold = 5000;
float current;
int BatVoltage = 5000;
int FetVoltage = 5000;
long TotalCurrent = 0;
boolean done = false;
boolean i = false;
unsigned long PrevMillis ;
unsigned long MillisPassed ;
 
void CL2(){
  lcd.setCursor(0, 1);// Second line first char
  lcd.print("                        ");
  lcd.setCursor(0, 1);// Second line first char
}  

void CL1(){
  lcd.setCursor(0, 0);// First line first char
  lcd.print("                        ");
  lcd.setCursor(0, 0);// First line first char
}
 
void setup() {
  pinMode(ledPin, OUTPUT);//activation led and enable for FET
  lcd.begin(16, 2);// set up the LCD's number of rows and columns: 
  delay(500);
  
  lcd.print("     HELLO     ");  // Print a message to the LCD.
  
  lcd.setCursor(0, 1);// Second line first char
  lcd.print("Detecting Bat"); // print voltage value
  
  delay(2000);
   
  lcd.setCursor(0, 1);// Second line first char
  lcd.print("                        ");
  
  lcd.setCursor(0, 1);// Second line first char
  digitalWrite(ledPin, HIGH);   // set the LED on
  sensorValue = analogRead(sensorPin);   // read the value from the sensor:
  digitalWrite(ledPin, LOW);   // set the LED off
  // Detecting battery type



  
  BatVoltage = map(sensorValue, 0, 4095, 0, 3316)/0.7522;
  if (BatVoltage > 4500){
    lcd.print("Warning high-V! ");
    done = true;}
  else if (BatVoltage > LiMinThreshold){
    lcd.print("Type:Li-Ion Bat ");
    SelectedMinThreshold = LiMinThreshold;}
  else if (BatVoltage > NmhMinThreshold){
    lcd.print("Type:NiMH/Cd Bat ");
    SelectedMinThreshold = NmhMinThreshold;}
  else{
    lcd.print("Unknown Bat V < 1");
    done = true;}
  lcd.print("V=");
  lcd.print(map(sensorValue, 0, 4095, 0, 3316)/0.7522); // print voltage value
  delay(3000); 
  CL2();
  PrevMillis = millis();
}
 
void loop() {

  

      int time = millis() / 1000;
    
      if (BatVoltage > SelectedMinThreshold && !done) {
      digitalWrite(ledPin, HIGH);   // set the LED on
      sensorValue = analogRead(sensorPin);   // read the value from the sensor:
      sensor2Value = analogRead(sensor2Pin);   // read the value from the FET:
      
      FetVoltage = (map(sensor2Value, 0, 4095, 0, 3316)/0.7554);
      BatVoltage = (map(sensorValue, 0, 4095, 0, 3316))/0.7522;
      current = (BatVoltage/3.3);
      
      CL1();
      
      lcd.setCursor(0, 0);// First line first char
      TotalCurrent=TotalCurrent+MillisPassed/1000*(BatVoltage-FetVoltage)/3.3/3.6;
      lcd.print("    I=");
      lcd.print(TotalCurrent/1000);     
      lcd.print("mAH");
      

      lcd.setCursor(0, 1);// Second line first char
      lcd.print("V=");
      lcd.print(BatVoltage/1000.0); // print voltage value
      lcd.print("V ");

      
      lcd.print("A=");
      lcd.print(current/1000);
      lcd.print("A"); 
      
      
      delay(1000); 
      MillisPassed = millis()- PrevMillis;
      PrevMillis = millis();
      
     
    }
    else
    {
      done=true;
      digitalWrite(ledPin, LOW);   // set the LED off - stop loading
      CL2();

      
      sensorValue = analogRead(sensorPin);   // read the value from the sensor:
      BatVoltage = map(sensorValue, 0, 4095, 0, 3316)/0.7522;
      lcd.setCursor(0, 1);// Second line first char
      lcd.print("V=");
      lcd.print(BatVoltage/1000.0); // print voltage value
      lcd.print("V ");
      lcd.print("I=");
      lcd.print(TotalCurrent/1000);     
      lcd.print("mAH");

         
    if(i==false) 
    { 
      i=true;
     lcd.setCursor(4, 0);
        if (time / 60 / 60 < 10) {
          lcd.print ("0");                  //часы
      }
      lcd.print (time / 60 / 60);
      lcd.print (":");
        if (time / 60 % 60 < 10) {
          lcd.print ("0");                  //минуты
      }
      lcd.print ((time / 60) % 60);
      lcd.print (":");
        if (time%60<10) { lcd.print ("0"); }//секунды
          lcd.print (time%60);
    }

      delay(1000);
    }
}

 

nik182
Offline
Зарегистрирован: 04.05.2015

Ты будешь смеяться, но и у меня много дисплеев не переваривают lcd.clear. Вернее переваривают, но подавать команду после них надо с большой задержкой. И задержку надо подбирать. Но больше 2 секунд ни разу не было. Поэтому я тоже чищу пробелами. Так получается быстрее.