Programem Arduino.
Programem Arduino.
Witam.
Mam nadzieję że się nikt nie pogniewa jak zapytam tutaj o kilka kwestii związanych z programem w Arduino.
Mianowicie mam popularny program na ESP8266 i wyświetlaczu oled który pokazuje dane z serwera Weatherunderground i Thingspeak-a. Wyświetla te dane w czterech przewijających się "ramkach".
Dane te chciałbym przesłać przez port szeregowy i nawet to działa ale problem jest tego typu że konkretne dane wypluwa mi jak głupi przez cały czas trwania danej ramki. Powoduje to niezły bajzel przy odczycie.
Jest jakaś funkcja lub sposób dzięki któremu prześlę interesujące mnie dane tylko raz tak aby nie zatrzymywać programu?
Mam nadzieję że się nikt nie pogniewa jak zapytam tutaj o kilka kwestii związanych z programem w Arduino.
Mianowicie mam popularny program na ESP8266 i wyświetlaczu oled który pokazuje dane z serwera Weatherunderground i Thingspeak-a. Wyświetla te dane w czterech przewijających się "ramkach".
Dane te chciałbym przesłać przez port szeregowy i nawet to działa ale problem jest tego typu że konkretne dane wypluwa mi jak głupi przez cały czas trwania danej ramki. Powoduje to niezły bajzel przy odczycie.
Jest jakaś funkcja lub sposób dzięki któremu prześlę interesujące mnie dane tylko raz tak aby nie zatrzymywać programu?
A proszę program:
Chciałbym aby dane wysyłane były tylko raz po wywołaniu konkretnej ramki. Teraz dane są wysyłane non stop przez cały czas trwania ramki, powoduje to niezły bajzel przy odczycie.
Pewnie bym sobie z tym poradził gdybym potrafił wysyłane wartości zapisać do zmiennych, wtedy porównanie nowego odczytu do starego, jeśli się różnią to wysyłam jeśli brak różnicy to nie wysyłam.
Kod: Zaznacz cały
#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <JsonListener.h>
#include "SSD1306Wire.h"
#include "OLEDDisplayUi.h"
#include "Wire.h"
#include "WundergroundClient.h"
#include "WeatherStationFonts.h"
#include "WeatherStationImages.h"
#include "TimeClient.h"
#include "ThingspeakClient.h"
/***************************
* Begin Settings
**************************/
// WIFI
const char* WIFI_SSID = "";
const char* WIFI_PWD = "";
// Setup
const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes
// Display Settings
const int I2C_DISPLAY_ADDRESS = 0x3c;
const int SDA_PIN = D6;
const int SDC_PIN = D5;
// TimeClient settings
const float UTC_OFFSET = 2;
// Wunderground Settings
const boolean IS_METRIC = true;
const String WUNDERGRROUND_API_KEY = "";
const String WUNDERGRROUND_LANGUAGE = "PL";
const String WUNDERGROUND_COUNTRY = "PL";
const String WUNDERGROUND_CITY = "Bilgoraj";
//Thingspeak Settings
const String THINGSPEAK_CHANNEL_ID = "271134";
const String THINGSPEAK_API_READ_KEY = "";
// Initialize the oled display for address 0x3c
// sda-pin=14 and sdc-pin=12
SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN);
OLEDDisplayUi ui( &display );
/***************************
* End Settings
**************************/
TimeClient timeClient(UTC_OFFSET);
// Set to false, if you prefere imperial/inches, Fahrenheit
WundergroundClient wunderground(IS_METRIC);
ThingspeakClient thingspeak;
// flag changed in the ticker function every 10 minutes
bool readyForWeatherUpdate = false;
String lastUpdate = "--";
Ticker ticker;
//declaring prototypes
void drawProgress(OLEDDisplay *display, int percentage, String label);
void updateData(OLEDDisplay *display);
void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
void drawThingspeak(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex);
void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state);
void setReadyForWeatherUpdate();
// Add frames
// this array keeps function pointers to all frames
// frames are the single views that slide from right to left
FrameCallback frames[] = { drawDateTime, drawCurrentWeather, drawForecast, drawThingspeak };
int numberOfFrames = 4;
OverlayCallback overlays[] = { drawHeaderOverlay };
int numberOfOverlays = 1;
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println();
// initialize dispaly
display.init();
display.clear();
display.display();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.setContrast(255);
WiFi.begin(WIFI_SSID, WIFI_PWD);
int counter = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
display.clear();
display.drawString(64, 10, "Connecting to WiFi");
display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole);
display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole);
display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole);
display.display();
counter++;
}
ui.setTargetFPS(30);
ui.setActiveSymbol(activeSymbole);
ui.setInactiveSymbol(inactiveSymbole);
// You can change this to
// TOP, LEFT, BOTTOM, RIGHT
ui.setIndicatorPosition(BOTTOM);
// Defines where the first frame is located in the bar.
ui.setIndicatorDirection(LEFT_RIGHT);
// You can change the transition that is used
// SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN
ui.setFrameAnimation(SLIDE_LEFT);
ui.setFrames(frames, numberOfFrames);
ui.setOverlays(overlays, numberOfOverlays);
// Inital UI takes care of initalising the display too.
ui.init();
Serial.println("");
display.flipScreenVertically();
updateData(&display);
display.flipScreenVertically();
ticker.attach(UPDATE_INTERVAL_SECS, setReadyForWeatherUpdate);
}
void loop() {
display.flipScreenVertically();
if (readyForWeatherUpdate && ui.getUiState()->frameState == FIXED) {
updateData(&display);
}
int remainingTimeBudget = ui.update();
if (remainingTimeBudget > 0) {
// You can do some work here
// Don't do stuff if you are below your
// time budget.
delay(remainingTimeBudget);
}
}
void drawProgress(OLEDDisplay *display, int percentage, String label) {
display->clear();
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(ArialMT_Plain_10);
display->drawString(64, 10, label);
display->drawProgressBar(2, 28, 124, 10, percentage);
display->display();
}
void updateData(OLEDDisplay *display) {
drawProgress(display, 10, "Updating time...");
timeClient.updateTime();
drawProgress(display, 30, "Updating conditions...");
wunderground.updateConditions(WUNDERGRROUND_API_KEY, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY);
drawProgress(display, 50, "Updating forecasts...");
wunderground.updateForecast(WUNDERGRROUND_API_KEY, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY);
drawProgress(display, 80, "Updating thingspeak...");
thingspeak.getLastChannelItem(THINGSPEAK_CHANNEL_ID, THINGSPEAK_API_READ_KEY);
lastUpdate = timeClient.getFormattedTime();
readyForWeatherUpdate = false;
drawProgress(display, 100, "Done...");
delay(1000);
}
void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(ArialMT_Plain_10);
String date = wunderground.getDate();
int textWidth = display->getStringWidth(date);
display->drawString(64 + x, 5 + y, date);
display->setFont(ArialMT_Plain_24);
String time = timeClient.getFormattedTime();
textWidth = display->getStringWidth(time);
display->drawString(64 + x, 15 + y, time);
display->setTextAlignment(TEXT_ALIGN_LEFT);
Serial.println(time);
}
void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
display->setFont(ArialMT_Plain_10);
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawString(40 + x, 5 + y, wunderground.getWeatherText());
display->setFont(ArialMT_Plain_24);
String temp = wunderground.getCurrentTemp() + "°C";
display->drawString(50 + x, 15 + y, temp);
int tempWidth = display->getStringWidth(temp);
display->setFont(Meteocons_Plain_42);
String weatherIcon = wunderground.getTodayIcon();
int weatherIconWidth = display->getStringWidth(weatherIcon);
display->drawString(22 + x - weatherIconWidth / 2, 05 + y, weatherIcon);
}
void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
drawForecastDetails(display, x, y, 0);
drawForecastDetails(display, x + 44, y, 2);
drawForecastDetails(display, x + 88, y, 4);
}
void drawThingspeak(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(ArialMT_Plain_10);
display->drawString(64 + x, 0 + y, "Thingspeak");
display->setFont(ArialMT_Plain_10);
display->drawString(20 + x, 30 + y, thingspeak.getFieldValue(0) + "°C");
display->drawString(20 + x, 15 + y, thingspeak.getFieldValue(3));
display->drawString(32 + x, 15 + y, "V");
display->drawString(90 + x, 15 + y, thingspeak.getFieldValue(1) + "%");
display->drawString(90 + x, 30 + y, thingspeak.getFieldValue(2) + "hPa");
Serial.print(" TEMP-");
Serial.print(thingspeak.getFieldValue(0));
Serial.print(" NAP-");
Serial.print(thingspeak.getFieldValue(3));
Serial.print(" RH-");
Serial.print(thingspeak.getFieldValue(1));
Serial.print(" PRESS-");
Serial.println(thingspeak.getFieldValue(2));
}
void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex) {
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(ArialMT_Plain_10);
String day = wunderground.getForecastTitle(dayIndex).substring(0, 3);
day.toUpperCase();
display->drawString(x + 20, y, day);
display->setFont(Meteocons_Plain_21);
display->drawString(x + 20, y + 12, wunderground.getForecastIcon(dayIndex));
Serial.print(wunderground.getForecastIcon(dayIndex));
Serial.print(",");
Serial.println(day);
display->setFont(ArialMT_Plain_10);
display->drawString(x + 20, y + 34, wunderground.getForecastLowTemp(dayIndex) + "|" + wunderground.getForecastHighTemp(dayIndex));
display->setTextAlignment(TEXT_ALIGN_LEFT);
}
void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {
display->setColor(WHITE);
display->setFont(ArialMT_Plain_10);
String time = timeClient.getFormattedTime().substring(0, 5);
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawString(0, 54, time);
display->setTextAlignment(TEXT_ALIGN_RIGHT);
String temp = wunderground.getCurrentTemp() + "°C";
display->drawString(128, 54, temp);
display->drawHorizontalLine(0, 52, 128);
}
void setReadyForWeatherUpdate() {
Serial.println("Setting readyForUpdate to true");
readyForWeatherUpdate = true;
}
Chciałbym aby dane wysyłane były tylko raz po wywołaniu konkretnej ramki. Teraz dane są wysyłane non stop przez cały czas trwania ramki, powoduje to niezły bajzel przy odczycie.
Pewnie bym sobie z tym poradził gdybym potrafił wysyłane wartości zapisać do zmiennych, wtedy porównanie nowego odczytu do starego, jeśli się różnią to wysyłam jeśli brak różnicy to nie wysyłam.
Nie znam tych bibliotek, ale zgaduję, że uaktualniają i dane o pogodzie i ekran "swoim tempem", tzn. kolejne wywołania funkcji rysują kolejne fazy (animacje ramek) w razie potrzeby.
Nie wiem, na ile Ty znasz ich działanie, więc zaproponuję takie rozwiązanie:
a w loop:
ten if możesz włożyć w "if (remainingTimeBudget > 0) "
W ten sposób uniezależnisz całkowicie wysyłanie danych przez port od wyświetlania.
Nie wiem, na ile Ty znasz ich działanie, więc zaproponuję takie rozwiązanie:
Kod: Zaznacz cały
#define CO_ILE_MS_WYSYLAC_SERIAL 1000
unsigned long ostatniaWysylka = 0
Kod: Zaznacz cały
if ((unsigned long)(millis() - ostatniaWysylka) >= CO_ILE_MS_WYSYLAC_SERIAL) {
ostatniaWysylka = millis();
Serial.print....
}
W ten sposób uniezależnisz całkowicie wysyłanie danych przez port od wyświetlania.
--
pozdrawiam,
Jarek Andrzejewski
pozdrawiam,
Jarek Andrzejewski
Poradziłem sobie z tym inaczej.
Sprawdzam czy są różnice w nowym i starym odczycie, jeśli są to wysyłam dane na uart.
Działa to ładnie.
Mam tylko problem z ramką ForecastDetails. W ramce tej jako że wyświetla ona prognozowaną pogodę na trzy dni,zmieniają się i ikony pogody i dni. Nie mam więc do czego porównywać odczytów bo zawsze są inne i zawsze następuje wysyłanie danych. Tak jak pisałem wcześniej powoduje to straszny burdel podczas odczytywania z Uart-a.
Masz jakiś pomysł jak to rozwiązać?
A i jeszcze jedno . Jak ze zmiennej "time" usunąć sekundy?
Sprawdzam czy są różnice w nowym i starym odczycie, jeśli są to wysyłam dane na uart.
Działa to ładnie.
Mam tylko problem z ramką ForecastDetails. W ramce tej jako że wyświetla ona prognozowaną pogodę na trzy dni,zmieniają się i ikony pogody i dni. Nie mam więc do czego porównywać odczytów bo zawsze są inne i zawsze następuje wysyłanie danych. Tak jak pisałem wcześniej powoduje to straszny burdel podczas odczytywania z Uart-a.
Masz jakiś pomysł jak to rozwiązać?
A i jeszcze jedno . Jak ze zmiennej "time" usunąć sekundy?
Możesz też zrobić "brzydko", ale prosto. Zrób trzy zmienne (zestawy zmiennych). Zapisz do nich wartości: do pierwszej zmiennej (zestawu zmiennych) wartość (wartości) prognozy na dzień X, do drugiej - na dzień Y, a do trzeciej na dzień Z. Potem, jak znów pobierzesz prognozę na konkretny dzień, to porównaj jej wartości z tymi zapamiętanymi dla danego dnia - i wyślij, jeśli będzie inna. Po wysłaniu zapisz wartość (wartości), żeby kolejne porównanie było z tą właśnie wysłaną.
No i polecam: http://helion.pl/ksiazki/jezyk-ansi-c-p ... jansic.htm (na pewno da się znaleźć kopię w sieci).
No i polecam: http://helion.pl/ksiazki/jezyk-ansi-c-p ... jansic.htm (na pewno da się znaleźć kopię w sieci).
--
pozdrawiam,
Jarek Andrzejewski
pozdrawiam,
Jarek Andrzejewski
Pokombinowałem i wyszło.
Tematu nie zamykam bo pewnie jeszcze się gdzieś zawiesze.
Kod: Zaznacz cały
void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex) {
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(ArialMT_Plain_10);
String day = wunderground.getForecastTitle(dayIndex).substring(0, 3);
day.toUpperCase();
display->drawString(x + 20, y, day);
display->setFont(Meteocons_Plain_21);
display->drawString(x + 20, y + 12, wunderground.getForecastIcon(dayIndex));
wgfi0 = wunderground.getForecastIcon(0);
wgfi2 = wunderground.getForecastIcon(2);
wgfi4 = wunderground.getForecastIcon(4);
if (wgfi0 != oldwgfi0 || wgfi2 != oldwgfi2 || wgfi4 != oldwgfi4){
Serial.print("Forecast-");
Serial.print(wgfi0);
Serial.print("-");
Serial.print("0");
Serial.print(",");
Serial.print(wgfi2);
Serial.print("-");
Serial.print("1");
Serial.print(",");
Serial.print(wgfi4);
Serial.print("-");
Serial.println("2");
oldwgfi0 = wgfi0;
oldwgfi2 = wgfi2;
oldwgfi4 = wgfi4;
}
display->setFont(ArialMT_Plain_10);
display->drawString(x + 20, y + 34, wunderground.getForecastLowTemp(dayIndex) + "|" + wunderground.getForecastHighTemp(dayIndex));
display->setTextAlignment(TEXT_ALIGN_LEFT);
}
Tematu nie zamykam bo pewnie jeszcze się gdzieś zawiesze.
To tylko na razie tak jest. Zmian będzie jeszcze więcej. Chcę jeszcze dołożyć do czujnika zewnętrznego sensor oświetlenia, odczyt faz księżyca z Weatherunderground no i muszę jeszcze jakoś sformatować lepiej te dane wysyłane przez Uart.ptja pisze:Dlaczego wysyłasz po jednym znaku? Nie lepiej np. Serial.println("-2"); ?