С дисплеем нокиа3410.
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <Wire.h>
#include "TinyBME280.h"
// Nokia LCD pin numbers
#define LCD_MOSI PINB2 //DIN,SDA,data
#define LCD_SCK PINB4 //CLK,SCL,clock
#define LCD_CD PINB1 //DC, D/C
#define LCD_RESET PINB0 //Res,reset
/*pin CS подключить на GND
pin Vout через конденсатор на GND */
/** Number of columns */
#define LCD_COL 96 //for Nokia 3310-84
/** Number of text rows */
#define LCD_ROW 10 //for Nokia 3310-6
int const sda = PB5;//pin 17
int const scl = PB7;//pin 19
extern const uint8_t SMALL_FONT[] PROGMEM;
const uint8_t SMALL_FONT[] PROGMEM = {
0x7C, 0x82, 0x82, 0x82, 0x7C, // 30 0
0x00, 0x84, 0xFE, 0x80, 0x00, // 31 1
0x84, 0xC2, 0xA2, 0x92, 0x8C, // 32 2
0x42, 0x82, 0x8A, 0x96, 0x62, // 33 3
0x30, 0x28, 0x24, 0xFE, 0x20, // 34 4
0x4E, 0x8A, 0x8A, 0x8A, 0x72, // 35 5
0x7C, 0x92, 0x92, 0x92, 0x64, // 36 6
0x02, 0xE2, 0x12, 0x0A, 0x06, // 37 7
0x6C, 0x92, 0x92, 0x92, 0x6C, // 38 8
0x4C, 0x92, 0x92, 0x92, 0x7C, // 39 9
0x00, 0x60, 0x60, 0x00, 0x00, // .
0x01, 0x01, 0x7F, 0x01, 0x01,// т
0x7F, 0x49, 0x49, 0x49, 0x41,//e
0xFF, 0x02, 0x0C, 0x02, 0xFF,//м
0x7F, 0x01, 0x01, 0x01, 0x7F,//п
0x7F, 0x09, 0x09, 0x09, 0x06,//p
0x07, 0x48, 0x48, 0x48, 0x3F,//у
0x7C, 0x12, 0x11, 0x12, 0x7C,//a
0x00, 0x0C, 0x12, 0x12, 0x0C,//gradus
0x3E, 0x41, 0x41, 0x41, 0x22,//c
0x7F, 0x49, 0x49, 0x49, 0x36,//в
0x40, 0x3E, 0x01, 0x01, 0x7F,//л
0x77, 0x08, 0x7F, 0x08, 0x77,//ж
0x7F, 0x08, 0x08, 0x08, 0x7F,//H
0x00, 0x7F, 0x48, 0x48, 0x30,//Ь
0x46, 0x26, 0x10, 0xC8, 0xC4,//%
0x60, 0x3F, 0x21, 0x3F, 0x60,//д
0x7F, 0x10, 0x08, 0x04, 0x7F,//и
0xF8, 0x20, 0x50, 0x88, 0x00,//к
0x3E, 0x41, 0x41, 0x41, 0x3E,//о
0xFE, 0x02, 0x02, 0x02, 0xFE,//п
0x40, 0xA8, 0xA8, 0xA8, 0xF0,//a
0x7C, 0x82, 0x82, 0x82, 0x44,//c
};
void setup() {
uint8_t val = (1 << LCD_SCK) | (1 << LCD_MOSI) | (1 << LCD_RESET) | (1 << LCD_CD);
PORTB &= ~val;
DDRB |= val;
PORTB |= (1 << LCD_RESET);
lcdCommand(0x21); // LCD Extended Commands.
lcdCommand(0xA1); // Set LCD Vop (Contrast).
lcdCommand(0x04); // Set Temp coefficent.
lcdCommand(0x14); // LCD bias mode 1:48.
lcdCommand(0x20); // LCD Normal commands
lcdCommand(0x0C); // Normal display, horizontal addressing
// clear nokia LCD
lcdCommand(0x80);
lcdCommand(0x40);
// Fill in the whole display with ZEROS
for(uint16_t index = 0; index < (LCD_COL * LCD_ROW); index++)
lcdData(0x00);
Wire.begin();
BME280setI2Caddress(0x76);
BME280setup();
}
void loop() {
int t = BME280temperature();
int p = BME280pressure()/100;
int h = BME280humidity();
lcdPrintChar(0, 22,26);//д
lcdPrintChar(0, 29,17);//а
lcdPrintChar(0, 36,20);//в
lcdPrintChar(0, 43,21);//л
lcdPrintChar(0, 50,12);//е
lcdPrintChar(0, 57,23);//н
lcdPrintChar(0, 64,27);//и
lcdPrintChar(0, 71,12);//е
lcdPrintChar(1,26,p/ 1000);
lcdPrintChar(1,33,(p/100) % 10);
lcdPrintChar(1,40,(p/ 10) % 10);
lcdPrintChar(1,47,p % 10);
lcdPrintChar(1, 54,28);//к
lcdPrintChar(1, 61,30);//п
lcdPrintChar(1, 68,31);//а
lcdPrintChar(3, 8, 11);//т
lcdPrintChar(3, 15,12);//е
lcdPrintChar(3, 22,13);//м
lcdPrintChar(3, 29,14);//п
lcdPrintChar(3, 36,12);//е
lcdPrintChar(3, 43,15);//р
lcdPrintChar(3, 50,17);//а
lcdPrintChar(3, 57,11);//т
lcdPrintChar(3, 64,16);//у
lcdPrintChar(3, 71,15);//р
lcdPrintChar(3, 78,17);//а
lcdPrintChar(4,26,t/ 1000);
lcdPrintChar(4,33,(t/ 100) % 10);
lcdPrintChar(4,40,10);
lcdPrintChar(4,45,(t/ 10) % 10);
// lcdPrintChar(4,54, t % 10);
lcdPrintChar(4,52, 18);
lcdPrintChar(4,59, 32);
lcdPrintChar(6, 15,20);//в
lcdPrintChar(6, 22,21);//л
lcdPrintChar(6, 29,17);//а
lcdPrintChar(6, 36,22);//ж
lcdPrintChar(6, 43,23);//н
lcdPrintChar(6, 50,29);//0
lcdPrintChar(6, 57,19);//с
lcdPrintChar(6, 64,11);//т
lcdPrintChar(6, 71,24);//ь
lcdPrintChar(7,26,h/1000 % 10);
lcdPrintChar(7,33,(h/100) % 10);
lcdPrintChar(7,40,10);
lcdPrintChar(7,45,(h/10) % 10);
// lcdPrintChar(7,54,h % 10);
lcdPrintChar(7,52,25);//%
}
void sspiOutMSB(uint8_t sck, uint8_t mosi, uint16_t data, uint8_t bits) {
uint16_t mask = (1 << (bits - 1));
uint8_t output = (1 << mosi);
uint8_t clock = (1 << sck);
while(bits) {
// Set data
if(data&mask)
PORTB |= output;
else
PORTB &= ~output;
// Bring the clock high
PORTB |= clock;
// Move to the next bit
mask = mask >> 1;
bits--;
// Bring the clock low again
PORTB &= ~clock;
}
}
void lcdData(uint8_t data) {
// Bring CD high
PORTB |= (1 << LCD_CD);
// Send the data
sspiOutMSB(LCD_SCK, LCD_MOSI, data, 8);
}
/** Send a command byte to the LCD
*
* @param cmd the command byte to send.
*/
void lcdCommand(uint8_t cmd) {
// Bring CD low
PORTB &= ~(1 << LCD_CD);
// Send the data
sspiOutMSB(LCD_SCK, LCD_MOSI, cmd, 8);
}
/** Write a single character
*/
void lcdPrintChar(uint8_t row, uint8_t col, uint8_t ch) {
// Set the starting address
const uint8_t *chdata = SMALL_FONT + (ch * 5);
lcdCommand(0x80 | col);
lcdCommand(0x40 | (row % LCD_ROW));
// And send the column data
for(uint8_t pixels = 0; pixels < 5; pixels++, chdata++) {
uint8_t data = pgm_read_byte_near(chdata);
lcdData(data);
// for double sized font put
// lcdData(data);
};
// Add the padding byte
//if(col < LCD_COL)
lcdData(0x00);
}
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <Wire.h>
#include "TinyBME280.h"
// Nokia LCD pin numbers
#define LCD_MOSI PINB4 //DIN,SDA,data
#define LCD_SCK PINB3 //CLK,SCL,clock
#define LCD_CD PINB2 //DC, D/C
#define LCD_RESET PINB1 //Res,reset
/*pin CS подключить на GND
pin Vout через конденсатор на GND */
/** Number of columns */
#define LCD_COL 96 //for Nokia 3310-84
/** Number of text rows */
#define LCD_ROW 10 //for Nokia 3310-6
int const sda = PB5;//pin 17
int const scl = PB7;//pin 19
#define DHT PIND0
const unsigned long Alarm = 300000; // time - 5 minutes
//unsigned long StartTime = 0; // start time
const int Dht = PIND1; // +dht11
byte _hum, _temp;
extern const uint8_t SMALL_FONT[] PROGMEM;
const uint8_t SMALL_FONT[] PROGMEM = {
0x00, 0x60, 0x60, 0x00, 0x00, // .
0x3E, 0x41, 0x49, 0x49, 0x7A,//g
};
extern const uint8_t BIG_FONT[] PROGMEM;
const uint8_t BIG_FONT[] PROGMEM = {
0x00,0xF0,0xFC,0xFE,0x06,0x02,0x06,0xFE,0xFC,0xF0,0x00,// 0
0x00,0x07,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x07,0x00,
0x00,0x00,0x08,0x0C,0xFC,0xFE,0xFE,0x00,0x00,0x00,0x00,// 1
0x00,0x20,0x20,0x20,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x00,
0x00,0x0C,0x0E,0x06,0x02,0x02,0x86,0xFE,0x7C,0x38,0x00,// 2
0x00,0x30,0x38,0x3C,0x36,0x33,0x31,0x30,0x30,0x38,0x00,
0x00,0x0C,0x0E,0x86,0x82,0x82,0xC6,0xFE,0x7C,0x38,0x00,// 3
0x00,0x18,0x38,0x30,0x20,0x20,0x31,0x3F,0x1F,0x0E,0x00,
0x00,0x00,0xC0,0x20,0x18,0x04,0xFE,0xFE,0xFE,0x00,0x00,// 4
0x00,0x03,0x02,0x02,0x02,0x22,0x3F,0x3F,0x3F,0x22,0x02,
0x00,0x00,0x7E,0x7E,0x46,0x46,0xC6,0xC6,0x86,0x00,0x00,// 5
0x00,0x18,0x38,0x30,0x20,0x20,0x30,0x3F,0x1F,0x0F,0x00,
0x00,0xC0,0xF0,0xF8,0xFC,0x4C,0xC6,0xC2,0x82,0x00,0x00,// 6
0x00,0x0F,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x0F,0x00,
0x00,0x06,0x06,0x06,0x06,0x06,0xC6,0xF6,0x3E,0x0E,0x00,// 7
0x00,0x00,0x00,0x30,0x3C,0x0F,0x03,0x00,0x00,0x00,0x00,
0x00,0x38,0x7C,0xFE,0xC6,0x82,0xC6,0xFE,0x7C,0x38,0x00,// 8
0x00,0x0E,0x1F,0x3F,0x31,0x20,0x31,0x3F,0x1F,0x0E,0x00,
0x00,0x78,0xFC,0xFE,0x86,0x02,0x86,0xFE,0xFC,0xF8,0x00,// 9
0x00,0x00,0x00,0x21,0x21,0x31,0x1D,0x1F,0x0F,0x03,0x00,
0xF0,0xF8,0x0C,0x06,0x02,0x02,0x02,0x02,0x0E,0x0C,0x00,// C
0x03,0x07,0x0C,0x18,0x10,0x10,0x10,0x10,0x1C,0x0C,0x00,
0x00,0x1C,0x22,0x22,0x22,0x1C,0x00,0x00,0x00,0x00,0x00,// degrees
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x1C,0x22,0x22,0x22,0x1C,0x80,0x40,0x20,0x10,0x08,// %
0x00,0x10,0x08,0x04,0x02,0x01,0x38,0x44,0x44,0x44,0x38,
0x00,0x00, 0x80, 0xC0, 0x60, 0x60,0x60, 0x60, 0xE0, 0xE0, 0x00,// Г
0x00,0x00, 0x03, 0x07, 0xCC, 0xCC,0xCC, 0xCC, 0xFF, 0x7F, 0x00,
0x00,0x00, 0xF8, 0xFC, 0x0C, 0x0C,0x0C, 0x0C, 0xF8, 0xF0, 0x00,//P
0x00,0x00, 0x7F, 0x7F, 0x03, 0x03,0x03, 0x03, 0x01, 0x00, 0x00,
0x00,0x00,0x00,0x00,0x40,0x60,0x60,0x60,0xE0,0xC0,0x00,//А
0x00,0x00,0x00,0x3C,0x7E,0x66,0x66,0x66,0x3F,0x7F,0x40,
0x88,0x48,0x29,0xDA,0x2C,0x32,0x32,0x4C,0x9A,0xA9,0x48,//Рress
0x00,0x06,0x49,0x29,0x88,0x48,0x28,0x08,0x48,0x24,0x03,
0x44,0x54,0x54,0xFE,0x01,0xFE,0x00,0xC6,0x29,0x29,0x46,//Тemp
0x00,0x01,0x71,0x8F,0x80,0x8F,0x70,0x07,0x08,0x08,0x04,
0x00,0x80,0x40,0x30,0x0E,0x07,0x38,0xE0,0xC0,0x80,0x00,//Нum
0x00,0x3E,0x41,0x80,0x80,0x80,0x80,0xC0,0xFF,0x7F,0x3E,
};
void setup() {
DDRD|=(1<<Dht);
PORTD = PORTD | 1<<Dht;
unitLCD();
clearLCD();
Wire.begin();
BME280setI2Caddress(0x76);
BME280setup();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}
void loop() {
do{
int t = BME280temperature();
int p = BME280pressure()/100;
dht_read(&_hum, &_temp);
lcdPrintBChar(6, 0, 18, 0, 0);
lcdPrintBChar(6, 34,_hum / 10%10, 0, 0);
lcdPrintBChar(6, 46,_hum %10, 0, 0);
lcdPrintBChar(6, 58, 12, 0, 0);
lcdPrintBChar(3, 1, 17, 0, 0);
lcdPrintBChar(3, 22,t/1000%10, 0, 0);
lcdPrintBChar(3, 34,t/100%10, 0, 0);
lcdPrintChar (4, 44,0);
lcdPrintBChar(3, 51,t/10%10, 0, 0);
lcdPrintBChar(3, 63, 11, 0, 0);
lcdPrintBChar(3, 73, 10, 0, 0);
lcdPrintBChar(0, 1, 16, 0, 0);
if(p/1000>0){
lcdPrintBChar(0,22,p / 1000, 0, 0) ;
lcdPrintBChar(0, 34,p /100%10, 0, 0);
lcdPrintBChar(0, 46,p/10%10, 0, 0);
lcdPrintBChar(0, 58,p%10, 0, 0);}
else {
lcdPrintBChar(0, 27,p /100%10, 0, 0);
lcdPrintBChar(0, 39,p/10%10, 0, 0);
lcdPrintBChar(0, 51,p%10, 0, 0);}
// lcdPrintChar (1, 63,1);
// lcdPrintBChar(0, 60, 13, 0, 0);
lcdPrintBChar(0, 70, 14, 0, 0);
lcdPrintBChar(0, 80, 15, 0, 0);
delay(1000);
}
while( millis() < Alarm);
PORTD = PORTD & ~(1<<Dht);
PORTB=0;
sleep_enable();
sleep_cpu();
}
void sspiOutMSB(uint8_t sck, uint8_t mosi, uint16_t data, uint8_t bits) {
uint16_t mask = (1 << (bits - 1));
uint8_t output = (1 << mosi);
uint8_t clock = (1 << sck);
while(bits) {
// Set data
if(data&mask)
PORTB |= output;
else
PORTB &= ~output;
// Bring the clock high
PORTB |= clock;
// Move to the next bit
mask = mask >> 1;
bits--;
// Bring the clock low again
PORTB &= ~clock;
}
}
void lcdData(uint8_t data) {
// Bring CD high
PORTB |= (1 << LCD_CD);
// Send the data
sspiOutMSB(LCD_SCK, LCD_MOSI, data, 8);
}
/** Send a command byte to the LCD
*
* @param cmd the command byte to send.
*/
void lcdCommand(uint8_t cmd) {
// Bring CD low
PORTB &= ~(1 << LCD_CD);
// Send the data
sspiOutMSB(LCD_SCK, LCD_MOSI, cmd, 8);
}
/** Write a single character
*/
void lcdPrintChar(uint8_t row, uint8_t col, uint8_t ch) {
// Set the starting address
const uint8_t *chdata = SMALL_FONT + (ch * 5);
lcdCommand(0x80 | col);
lcdCommand(0x40 | (row % LCD_ROW));
// And send the column data
for(uint8_t pixels = 0; pixels < 5; pixels++, chdata++) {
uint8_t data = pgm_read_byte_near(chdata);
lcdData(data);
// for double sized font put
// lcdData(data);
};
// Add the padding byte
//if(col < LCD_COL)
lcdData(0x00);
}
void clearLCD()
{ lcdCommand(0x80);
lcdCommand(0x40);
// Fill in the whole display with ZEROS
for(uint16_t index = 0; index < (LCD_COL * LCD_ROW); index++)
lcdData(0x00);}
void unitLCD()
{
uint8_t val = (1 << LCD_SCK) | (1 << LCD_MOSI) | (1 << LCD_RESET) | (1 << LCD_CD);
PORTB &= ~val;
DDRB |= val;
PORTB |= (1 << LCD_RESET);
lcdCommand(0x21); // LCD Extended Commands.
lcdCommand(0xA1); // Set LCD Vop (Contrast).
lcdCommand(0x04); // Set Temp coefficent.
lcdCommand(0x14); // LCD bias mode 1:48.
lcdCommand(0x20); // LCD Normal commands
lcdCommand(0x0C); // Normal display, horizontal addressing
}
// общая функция опроса датчика
byte dht_read(byte *hum, byte* temp) {
byte data[5];// массив под данные датчика
byte error=dht_start();// стартуем и получаем код ошибки в переменную
if (error) return error; // если есть ошибки выходим с кодом ошибки
// получаем 5 байт от датчика
for (byte i=0; i<5; i++)
{
data[i]=dht_byte();
}
if (data[0]+data[1]+data[2]+data[3]!=data[4]) return 3; // если контрольная сумма не сошлась вернем ошибку 3
*hum=data[0];// пишем данные влажности
*temp=data[2];// пишем данные температуры
return 0;// вернем 0 - ошибок нет.
}
// функция передачи условия "старт" на линию и проверка ответов от датчика.
byte dht_start(){
DDRD|=(1<<DHT);// притянули линию к земле - 0
_delay_ms(20);// пауза 20 мс
DDRD&=~(1<<DHT);// отпустили линию - 1
_delay_us(40);// ждем 40 мкс чтобы попасть в середину низкого сигнала
if (PIND&(1<<DHT)) return 1; // если на линии 1 ошибка - "датчик не ответил"
_delay_us(80); // ждем 80 мкс чтобы попасть в середину высокого сигнала
if (!(PIND&(1<<DHT))) return 2; // если на линии 0 ошибка - "датчик не готов "
while(PIND&(1<<DHT));// ждем пока датчик не притянет линию к земле.
return 0;// ошибок нет
}
// получение байта от датчика
byte dht_byte(){
byte i=8, byte=0;// переменная для цикла и под байт
while(i--){
while(!(PIND&(1<<DHT)));// ждем пока линия не поднимится в 1
_delay_us(40);// отступаем 40 мкс
if (PIND&(1<<DHT)) {// если на линии 1 = приняли 1
byte|=(1<<i);// поднимаем итый бит в 1
while(PIND&(1<<DHT));// ждем пока линия упадет в 0
}
}
return byte;// возвращаем полученный байт
}
void lcdPrintBChar(uint8_t row, uint8_t col, uint8_t ch, bool big, bool invert) {
// Set the starting address
const uint8_t *chdata = BIG_FONT + (ch * 22);
for(uint8_t rowused = row; rowused < row+2; rowused++) {
lcdCommand(0x80 | col);
lcdCommand(0x40 | (rowused % LCD_ROW));
// And send the column data
for(uint8_t pixels = 0; pixels < 11; pixels++, chdata++) {
uint8_t data = pgm_read_byte_near(chdata);
//double sized font
lcdData(invert?~data:data);
if (big) lcdData(invert?~data:data);
};
}
// Add the padding byte
if(col < LCD_COL)
lcdData(invert?0xFF:0x00);
}