37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞不掂的问题,希望能够抛砖引玉。
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十三:0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十三: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
项目二十八:Adafruit_SSD1306 综合显示测试
实验接脚: 0.96寸OLED液晶屏SDA接A4, SCL接A5
实验开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十七: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
项目二十八:Adafruit_SSD1306 综合显示测试
实验接脚: 0.96寸OLED液晶屏SDA接A4, SCL接A5
*/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED 显示宽度,以像素为单位
#define SCREEN_HEIGHT 64 // OLED 显示高度,以像素为单位
// 连接到 I2C(SDA、SCL 引脚)的 SSD1306 显示器的声明
// I2C 的引脚由 Wire 库定义。
// 在 arduino UNO 上:A4(SDA)、A5(SCL)
// 在 arduino MEGA 2560 上:20(SDA), 21(SCL)
// 在 arduino LEONARDO 上:2(SDA), 3(SCL), ...
#define OLED_RESET 4 // 重置引脚 #(如果共享 Arduino 重置引脚,则为 1)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define NUMFLAKES 10 // 动画示例中的雪花数量
#define LOGO_HEIGHT 16
#define LOGO_WIDTH 16
static const unsigned char PROGMEM logo_bmp[] =
{ 0b00000000, 0b11000000,
0b00000001, 0b11000000,
0b00000001, 0b11000000,
0b00000011, 0b11100000,
0b11110011, 0b11100000,
0b11111110, 0b11111000,
0b01111110, 0b11111111,
0b00110011, 0b10011111,
0b00011111, 0b11111100,
0b00001101, 0b01110000,
0b00011011, 0b10100000,
0b00111111, 0b11100000,
0b00111111, 0b11110000,
0b01111100, 0b11110000,
0b01110000, 0b01110000,
0b00000000, 0b00110000
};
void setup() {
Serial.begin(9600);
// SSD1306_VCC = 从内部 3.3V 产生显示电压
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // 不要继续,永远循环
}
// 在屏幕上显示初始显示缓冲区内容 --
// 库使用 Adafruit 启动画面对其进行初始化。
display.display();
delay(500);
// 清除缓冲区
display.clearDisplay();
// 用白色绘制单个像素
display.drawPixel(10, 10, SSD1306_WHITE);
// 在屏幕上显示显示缓冲区。 你必须在之后调用 display()
// 绘制命令使它们在屏幕上可见!
display.display();
delay(500);
// 在每个绘图命令之后都不需要 display.display(),
// 除非那是你想要的......相反,你可以批量处理
// 绘制操作,然后通过调用一次更新屏幕
// display.display(). 这些示例演示了这两种方法......
testdrawline(); // Draw many lines
testdrawrect(); // Draw rectangles (outlines)
testfillrect(); // Draw rectangles (filled)
testdrawcircle(); // Draw circles (outlines)
testfillcircle(); // Draw circles (filled)
testdrawroundrect(); // Draw rounded rectangles (outlines)
testfillroundrect(); // Draw rounded rectangles (filled)
testdrawtriangle(); // Draw triangles (outlines)
testfilltriangle(); // Draw triangles (filled)
testdrawchar(); // Draw characters of the default font
testdrawstyles(); // Draw 'stylized' characters
testscrolltext(); // Draw scrolling text
testdrawbitmap(); // Draw a small bitmap image
// 反转和恢复显示,中间暂停
display.invertDisplay(true);
delay(500);
display.invertDisplay(false);
delay(500);
testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // 动画位图
}
void loop() {
}
void testdrawline() {
int16_t i;
display.clearDisplay(); // 清除显示缓冲区
for (i = 0; i < display.width(); i += 4) {
display.drawLine(0, 0, i, display.height() - 1, SSD1306_WHITE);
display.display(); // 用每条新画的线更新屏幕
delay(1);
}
for (i = 0; i < display.height(); i += 4) {
display.drawLine(0, 0, display.width() - 1, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for (i = 0; i < display.width(); i += 4) {
display.drawLine(0, display.height() - 1, i, 0, SSD1306_WHITE);
display.display();
delay(1);
}
for (i = display.height() - 1; i >= 0; i -= 4) {
display.drawLine(0, display.height() - 1, display.width() - 1, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for (i = display.width() - 1; i >= 0; i -= 4) {
display.drawLine(display.width() - 1, display.height() - 1, i, 0, SSD1306_WHITE);
display.display();
delay(1);
}
for (i = display.height() - 1; i >= 0; i -= 4) {
display.drawLine(display.width() - 1, display.height() - 1, 0, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for (i = 0; i < display.height(); i += 4) {
display.drawLine(display.width() - 1, 0, 0, i, SSD1306_WHITE);
display.display();
delay(1);
}
for (i = 0; i < display.width(); i += 4) {
display.drawLine(display.width() - 1, 0, i, display.height() - 1, SSD1306_WHITE);
display.display();
delay(1);
}
delay(1000);
}
void testdrawrect(void) {
display.clearDisplay();
for (int16_t i = 0; i < display.height() / 2; i += 2) {
display.drawRect(i, i, display.width() - 2 * i, display.height() - 2 * i, SSD1306_WHITE);
display.display(); // 使用每个新绘制的矩形更新屏幕
delay(1);
}
delay(1000);
}
void testfillrect(void) {
display.clearDisplay();
for (int16_t i = 0; i < display.height() / 2; i += 3) {
// 使用 INVERSE 颜色,因此矩形交替白色/黑色
display.fillRect(i, i, display.width() - i * 2, display.height() - i * 2, SSD1306_INVERSE);
display.display(); // 使用每个新绘制的矩形更新屏幕
delay(1);
}
delay(1000);
}
void testdrawcircle(void) {
display.clearDisplay();
for (int16_t i = 0; i < max(display.width(), display.height()) / 2; i += 2) {
display.drawCircle(display.width() / 2, display.height() / 2, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(1000);
}
void testfillcircle(void) {
display.clearDisplay();
for (int16_t i = max(display.width(), display.height()) / 2; i > 0; i -= 3) {
// The INVERSE color is used so circles alternate white/black
display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
display.display(); // 使用每个新绘制的圆圈更新屏幕
delay(1);
}
delay(1000);
}
void testdrawroundrect(void) {
display.clearDisplay();
for (int16_t i = 0; i < display.height() / 2 - 2; i += 2) {
display.drawRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i,
display.height() / 4, SSD1306_WHITE);
display.display();
delay(1);
}
delay(1000);
}
void testfillroundrect(void) {
display.clearDisplay();
for (int16_t i = 0; i < display.height() / 2 - 2; i += 2) {
// 使用 INVERSE 颜色,因此圆形矩形交替白色/黑色
display.fillRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i,
display.height() / 4, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(1000);
}
void testdrawtriangle(void) {
display.clearDisplay();
for (int16_t i = 0; i < max(display.width(), display.height()) / 2; i += 5) {
display.drawTriangle(
display.width() / 2 , display.height() / 2 - i,
display.width() / 2 - i, display.height() / 2 + i,
display.width() / 2 + i, display.height() / 2 + i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(1000);
}
void testfilltriangle(void) {
display.clearDisplay();
for (int16_t i = max(display.width(), display.height()) / 2; i > 0; i -= 5) {
// 使用 INVERSE 颜色,因此三角形交替白色/黑色
display.fillTriangle(
display.width() / 2 , display.height() / 2 - i,
display.width() / 2 - i, display.height() / 2 + i,
display.width() / 2 + i, display.height() / 2 + i, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(1000);
}
void testdrawchar(void) {
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
display.cp437(true); // Use full 256 char 'Code Page 437' font
// 并非所有字符都适合显示。 这是正常的。
// 库将绘制它可以绘制的内容,其余部分将被剪切。
for (int16_t i = 0; i < 256; i++) {
if (i == '\n') display.write(' ');
else display.write(i);
}
display.display();
delay(1000);
}
void testdrawstyles(void) {
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
display.println(F("Hello, world!"));
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
display.println(3.141592);
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.print(F("0x")); display.println(0xDEADBEEF, HEX);
display.display();
delay(1000);
}
void testscrolltext(void) {
display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 0);
display.println(F("scroll"));
display.display(); // Show initial text
delay(100);
// 向各个方向滚动,中间暂停:
display.startscrollright(0x00, 0x0F);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrollleft(0x00, 0x0F);
delay(1000);
display.stopscroll();
delay(1000);
display.startscrolldiagright(0x00, 0x07);
delay(1000);
display.startscrolldiagleft(0x00, 0x07);
delay(1000);
display.stopscroll();
delay(1000);
}
void testdrawbitmap(void) {
display.clearDisplay();
display.drawBitmap(
(display.width() - LOGO_WIDTH ) / 2,
(display.height() - LOGO_HEIGHT) / 2,
logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
display.display();
delay(1000);
}
#define XPOS 0 //在下面的函数中索引到“图标”数组
#define YPOS 1
#define DELTAY 2
void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
int8_t f, icons[NUMFLAKES][3];
// 初始化“雪花”位置
for (f = 0; f < NUMFLAKES; f++) {
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
Serial.print(F("x: "));
Serial.print(icons[f][XPOS], DEC);
Serial.print(F(" y: "));
Serial.print(icons[f][YPOS], DEC);
Serial.print(F(" dy: "));
Serial.println(icons[f][DELTAY], DEC);
}
for (;;) { // Loop forever...
display.clearDisplay(); // Clear the display buffer
// Draw each snowflake:
for (f = 0; f < NUMFLAKES; f++) {
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
}
display.display(); // Show the display buffer on the screen
delay(200); // Pause for 1/10 second
// 然后更新每个薄片的坐标...
for (f = 0; f < NUMFLAKES; f++) {
icons[f][YPOS] += icons[f][DELTAY];
// If snowflake is off the bottom of the screen...
if (icons[f][YPOS] >= display.height()) {
// Reinitialize to a random position, just off the top
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
}
}
}
}
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十七: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
项目二十八:Adafruit_SSD1306 综合显示测试
实验接脚: 0.96寸OLED液晶屏SDA接A4, SCL接A5
Arduino实验场景图
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十三: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
项目二十九:SSD1306 显示测试
实验接脚: 0.96寸OLED液晶屏SDA接A4, SCL接A5
实验开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十七: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
项目二十九:SSD1306 显示测试
实验接脚: 0.96寸OLED液晶屏SDA接A4, SCL接A5
*/
#include "ssd1306.h"
#include "nano_gfx.h"
#include "sova.h"
//下面的心脏图像是直接在闪存中定义的。这减少了 SRAM 消耗。
// 图像定义为从下到上(位),从左到正确(字节)。
const PROGMEM uint8_t heartImage[8] = {
0B00001110,
0B00011111,
0B00111111,
0B01111110,
0B01111110,
0B00111101,
0B00011001,
0B00001110
};
//定义精灵宽度。 宽度可以是任意大小。
//但精灵高度总是假定为 8 像素(单字节中的位数)。
const int spriteWidth = sizeof(heartImage);
SAppMenu menu;
const char *menuItems[] ={
"draw bitmap",
"sprites",
"fonts",
"canvas gfx",
"draw lines",
};
static void bitmapDemo(){
ssd1306_drawBitmap(0, 0, 128, 64, Sova);
delay(1000);
ssd1306_invertMode();
delay(2000);
ssd1306_normalMode();
}
static void spriteDemo(){
ssd1306_clearScreen();
/* Declare variable that represents our sprite */
SPRITE sprite;
/* Create sprite at 0,0 position. The function initializes sprite structure. */
sprite = ssd1306_createSprite( 0, 0, spriteWidth, heartImage );
for (int i = 0; i < 250; i++)
{
delay(15);
sprite.x++;
if (sprite.x >= ssd1306_displayWidth())
{
sprite.x = 0;
}
sprite.y++;
if (sprite.y >= ssd1306_displayHeight())
{
sprite.y = 0;
}
/* Erase sprite on old place. The library knows old position of the sprite. */
sprite.eraseTrace();
/* Draw sprite on new place */
sprite.draw();
}
}
static void textDemo(){
ssd1306_setFixedFont(ssd1306xled_font6x8);
ssd1306_clearScreen();
ssd1306_printFixed(0, 8, "Normal text", STYLE_NORMAL);
ssd1306_printFixed(0, 16, "Bold text", STYLE_BOLD);
ssd1306_printFixed(0, 24, "Italic text", STYLE_ITALIC);
ssd1306_negativeMode();
ssd1306_printFixed(0, 32, "Inverted bold", STYLE_BOLD);
ssd1306_positiveMode();
delay(3000);
}
static void canvasDemo(){
uint8_t buffer[64 * 16 / 8];
NanoCanvas canvas(64, 16, buffer);
ssd1306_setFixedFont(ssd1306xled_font6x8);
ssd1306_clearScreen();
canvas.clear();
canvas.fillRect(10, 3, 80, 5, 0xFF);
canvas.blt((ssd1306_displayWidth() - 64) / 2, 1);
delay(500);
canvas.fillRect(50, 1, 60, 15, 0xFF);
canvas.blt((ssd1306_displayWidth() - 64) / 2, 1);
delay(1500);
canvas.printFixed(20, 1, " DEMO ", STYLE_BOLD );
canvas.blt((ssd1306_displayWidth() - 64) / 2, 1);
delay(3000);
}
static void drawLinesDemo(){
ssd1306_clearScreen();
for (uint8_t y = 0; y < ssd1306_displayHeight(); y += 8)
{
ssd1306_drawLine(0, 0, ssd1306_displayWidth() - 1, y);
}
for (uint8_t x = ssd1306_displayWidth() - 1; x > 7; x -= 8)
{
ssd1306_drawLine(0, 0, x, ssd1306_displayHeight() - 1);
}
delay(3000);
}
void setup(){
/* Select the font to use with menu and all font functions */
ssd1306_setFixedFont(ssd1306xled_font6x8);
ssd1306_128x64_i2c_init();
// ssd1306_128x64_spi_init(-1, 0, 1); // Use this line for nano pi (RST not used, 0=CE, gpio1=D/C)
// ssd1306_128x64_spi_init(3,4,5); // Use this line for Atmega328p (3=RST, 4=CE, 5=D/C)
// ssd1306_128x64_spi_init(24, 0, 23); // Use this line for Raspberry (gpio24=RST, 0=CE, gpio23=D/C)
// ssd1306_128x64_spi_init(22, 5, 21); // Use this line for ESP32 (VSPI) (gpio22=RST, gpio5=CE for VSPI, gpio21=D/C)
// composite_video_128x64_mono_init(); // Use this line for ESP32 with Composite video support
ssd1306_clearScreen();
ssd1306_createMenu( &menu, menuItems, sizeof(menuItems) / sizeof(char *) );
ssd1306_showMenu( &menu );
}
void loop(){
delay(1000);
switch (ssd1306_menuSelection(&menu))
{
case 0:
bitmapDemo();
break;
case 1:
spriteDemo();
break;
case 2:
textDemo();
break;
case 3:
canvasDemo();
break;
case 4:
drawLinesDemo();
break;
default:
break;
}
ssd1306_clearScreen( );
ssd1306_showMenu(&menu);
delay(500);
ssd1306_menuDown(&menu);
ssd1306_updateMenu(&menu);
}
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十三: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
项目三十: OLED 显示串口信息
实验接脚: 0.96寸OLED液晶屏SDA接A4, SCL接A5
实验开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十七: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
项目三十: OLED 显示串口信息
实验接脚: 0.96寸OLED液晶屏SDA接A4, SCL接A5
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
void setup()
{
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
Serial.println("OLED准备就绪");
delay(1000);
}
void loop(){
String inString = "";
while (Serial.available() > 0) {
char inChar = Serial.read(); //
inString += (char)inChar;
delay(10);
}
if (inString != ""){
display.setTextSize(2); //设置字体大小
display.setTextColor(WHITE); //设置字体颜色白色
display.setCursor(0, 0); //设置字体的起始位置
display.println(inString); //显示输入数据
display.display(); //显示信息
Serial.print("串口输入=");
Serial.println(inString);
delay (1000);
display.clearDisplay();
}
}
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十三: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
项目三十: OLED 显示串口信息
实验接脚: 0.96寸OLED液晶屏SDA接A4, SCL接A5
OLED 实时读取串口信息,可应用于诸多适用场合,方便人们在第一时间识别和处理一些信息(需要串口助手)
实验串口绘图器返回情况
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十三: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
项目三十: OLED 显示串口信息
实验接脚: 0.96寸OLED液晶屏SDA接A4, SCL接A5
实验场景图
hacker_2023.07.28
666