ARDUINO
I2C komunikace Wemos<->PROmini Pavel
11:01:37
12.12.2018
I2C komunikace Wemos<->PROmini


Protože si chci sestavit meteostanici s měření rychlosti větru a už teď toho má Dobby na práci až dost tak chci použít Arduino PROmini (ATmega168 8MHz 3.3v) jako počítadlo impulsů a takto připravená data teprve posílat do Dobbyho (Wemos D1 mini) po sběrnici I2C kterou už stejně používám pro displej a pro hodiny reálného času.


Princip jednoduchý, leč problémů vícero. Zásadní je uvědomit si že I2C není UART, to znamená že komunikace běží vždy jen jedním směrem.


Každé zařízení Slave musí mít sedmi bitovou adresu (0-127) a veškerá komunikace probíhá v bajtech. Master adresu nepotřebuje protože na sběrnici je jen jeden a dotazy na Slave posílá on, Slave prostě jen naslouchá a pokud je dotaz na něj, tak odpoví.


Tady je upravený kód pro Dobbyho: (záměrně je odstraněná WiFi část)
#include <Wire.h>
#include <OneWire.h>
#include <ESP8266WiFi.h>
#include "RTClib.h"
#include <U8g2lib.h>
#include <Arduino.h>


#define LED D0 //výstup na relé pro rozsvícení
#define I2D D1 //sběrnice I2C data
#define I2C D2 //sběrnice I2C hodiny
#define NO1 D3
#define TLA D4 //vstup pro tlačítko Dobbyho
#define TLB D5 //vstup pro tlačítko Dobbyho
#define TEP D6 //sběrnice OneWire pro teploměry
#define NO3 D7
#define NO4 D8


byte h;
byte hh;
byte m;
byte s;
byte da;
byte dd;
byte mm;
byte yy;
byte msb;
byte lsb;
int impu=0;
unsigned long ut=0;

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
RTC_DS3231 rtc;
DateTime now;

void setup() {
Serial.begin(115200);
rtc.begin();
u8g2.begin();
u8g2.enableUTF8Print();
Wire.begin();
}

void loop() {
byte b;
Wire.requestFrom(8,2); //požádej zařízení s adresou 8 o dva bajty
b=Wire.read(); //načti první bajt
impu=int(b*256); //první bajt vynásob 256, to je bitový posun na horní polovinu typu int
b=Wire.read(); //načti druhý bajt
impu+=int(b); // k horní polovině přičti dolní polovinu a máš celé 16bitové slovo pro int
Serial.print("impu=");
Serial.println(impu);
displej(0,0);
delay(500);
}

void displej(int fun, int fpro) {
String text = "";
int a = 0, b, c, d;
now = rtc.now();
h = now.hour();
m = now.minute();
s = now.second();
dd = now.day();
mm = now.month();
yy = now.year();
ut = now.unixtime();

u8g2.clearBuffer();
u8g2.setFontRefHeightExtendedText();
u8g2.setDrawColor(1);
u8g2.setFontPosTop();
u8g2.setFontDirection(0);
u8g2.setFont(u8g2_font_helvB18_tf);
u8g2.drawRFrame(0, 0, 128, 24, 3);
u8g2.setCursor(10, 2);
if (h < 10) u8g2.print(" ");
u8g2.print(h, DEC);
u8g2.print(":");
if (m < 10) u8g2.print("0");
u8g2.print(m, DEC);
u8g2.print(":");
if (s < 10) u8g2.print("0");
u8g2.print(s, DEC);

u8g2.setCursor(0, 32);
u8g2.print(String(impu));
u8g2.sendBuffer();
}



a tady je kousek testovacího kódu pro Arduino MINIpro


#include <Wire.h>

int impu=0; // tady by mělo být unsigned, protože až počítadlo dojde zhruba na 32000 tak signed int spadne do záporných hodnot (nevadí, protože to stejně převádím na byte)
void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(receiveEvent); // register event
Serial.begin(115200); // start serial for output
Serial.println("Start");
}

void loop() {
impu++; //do zblbnutí přičítej jedničku, až dorazíš na
delay(200);
}

void receiveEvent(int howMany) {
byte b[2];
b[0]=impu/256;
b[1]=impu-(impu/256*256);
Wire.write(b,2);
}


Celé to funguje tak že Dobby pošle dotaz na PROmini a to mu odpoví. Dobby si zobrazí na dislpeji hodiny z RTC a k tomu hodnotu kterou dostal. Jediná záludnost a zrada pro začátečníka, je ve funkci WRITE kde je parametrem buď BYTE, nebo STRING, nebo pole BYTE. Já používám pole BYTE protože potřebuji přenést víc než jeden BYTE. Při pokusech jsem používal funkci opakovaně, to nefunguje, prostě se musí použít jen jednou a poslat celou odpověď najednou.


Kód budu ještě vylepšovat, přibude tam přerušení pro počítání impulzů z větrníku (to je ta pitomost co se otáčí podle toho jak fouká vítr). Dobby se bude ptát jednou za sekundu aby dostal rychlost větru v m/s, PROmini po každém dotazu musí vynulovat počítadlo. Tenhle příklad je jen "nástřel" toho jak ta komunikace probíhat může.


A nakonec jen maličká drobnost, Dobby vykresluje displej a žádá o data dvakrát za sekundu, PROmini připočítává 1 pětkrát za sekundu,kdyby náhodou to někdo chtěl testovat :)
Zpět