本来介绍如何在Nano上面,通过SSD1306设计一个仪表盘
SSD1306基本设置请参照下面的链接
Arduino Nano 驱动OLED测试入门(一)(软IIC以及硬IIC链接SSD1306屏)
SSD1306库函数参数讲解参照下面的链接
Arduino Nano 驱动OLED测试入门(二) U8glib 库函数及参数讲解
本文通过一个可调电位器,设计一个电压仪表盘。
屏的连线方式请参照入门(一),电位器三端,一端接地,一端接5V,另一端接Nano的模拟输入端A1 引脚。
程序中定义了三个变量,p代表AD采集的值,p的范围从0到1023,w和m分别是通过map函数重映射的值,map是一个arduino的库函数,定义为:
map(value, fromLow, fromHigh, toLow, toHigh)
value的取值范围是fromLow to fromHigh,该函数的作用是把value从一个范围变换到另一个范围。
w可以理解为百分率,p为1023的时候,w为100;
m可以理解为仪表盘指的偏转角度,初始位置为180度。
源代码参照国外例子,但源代码中关于指针角度的换算很让人费解,我重新改动了一下,更易于理解。
注释掉的部分为原代码,希望了解原作者思路的同学可以自己选择注释看一下。
p = analog read (potmeterPin);
w = map (p, 0, 1023, 0, 100);
//m = map (p, 0, 1023, 0, 90);
m = map (p, 0, 1023, 180, 0);
程序中用到一个库函数map();
函数的作用是把
下面直接上代码,主要注意两个地方,一是确保你的Arduino IDE里已经添加了 U8glib的库文件,二是设置显示屏参数:
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);
/*
Analog gauge v1.03
- Shows half circle gauge with scale labels
- Shows digital value, 00 - 100 aligned
- Shows gauge label
21/12/2015 - Rudi Imbrechts
23/06/2020 - MGM
http://arduinows.blogspot.com
*/
#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);
//U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9, 12); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Res = 12
// For OLED display with SH1106 driver. If you use another display,
// then please check the u8glib documentation and website at
// https://github.com/olikraus/u8glib
int xmax=128; // max length x-axis
int ymax=62; // max length y-axis
int xcenter=xmax/2; // center of x-axis
int ycenter=ymax/2+10; // center of y-axis
int arc=ymax/2;
int angle=0;
char* label[] = {
"LOAD","COOLANT","INTAKE", "VOLT"}; // some custom gauge labels
int labelXpos[] = {
53, 45, 49, 53}; // predefined x-position of a gauge label
#define potmeterPin A1 // simulate analogue value with potentiometer
int p, w, m;
u8g_uint_t xx=0;
// ------------------------------------------------- void gauge() ------------------------------------------
void gauge(uint8_t angle) {
// draw border of the gauge
u8g.drawCircle(xcenter,ycenter,arc+6, U8G_DRAW_UPPER_RIGHT);
u8g.drawCircle(xcenter,ycenter,arc+4, U8G_DRAW_UPPER_RIGHT);
u8g.drawCircle(xcenter,ycenter,arc+6, U8G_DRAW_UPPER_LEFT);
u8g.drawCircle(xcenter,ycenter,arc+4, U8G_DRAW_UPPER_LEFT);
// draw the needle
//float x1=sin(2*angle*2*3.14/360); // needle position
//float y1=cos(2*angle*2*3.14/360); //needle position
float x1=cos(angle*2*3.14/360); // changed by MGM
float y1=sin(angle*2*3.14/360);
u8g.drawLine(xcenter, ycenter, xcenter+arc*x1, ycenter-arc*y1);
u8g.drawDisc(xcenter, ycenter, 5, U8G_DRAW_UPPER_LEFT);
u8g.drawDisc(xcenter, ycenter, 5, U8G_DRAW_UPPER_RIGHT);
u8g.setFont(u8g_font_chikita);
// show scale labels
u8g.drawStr( 20, 42, "0");
u8g.drawStr( 25, 18, "25");
u8g.drawStr( 60, 14, "50");
u8g.drawStr( 95, 18, "75");
u8g.drawStr( 105, 42, "100");
// show gauge label
u8g.setPrintPos(labelXpos[1],32);
u8g.print(label[1]);
// show digital value and align its position
u8g.setFont(u8g_font_osb18);
u8g.setPrintPos(54,60);
if (w<10){
// leading 0 when value less than 10
u8g.print("0");
}
if (w>99) {
// position at 100%
u8g.setPrintPos(47,60);
}
u8g.print(w);
}
// ------------------------------------------------- void setup() ------------------------------------------
void setup(void) {
pinMode(potmeterPin, INPUT);
u8g.setFont(u8g_font_chikita);
u8g.setColorIndex(1); // Instructs the display to draw with a pixel on.
// assign default color value
if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
u8g.setColorIndex(255); // white
}
else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
u8g.setColorIndex(3); // max intensity
}
else if ( u8g.getMode() == U8G_MODE_BW ) {
u8g.setColorIndex(1); // pixel on
}
// else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
// u8g.setHiColorByRGB(255,255,255);
// }
}
// ------------------------------------------------- void loop() ------------------------------------------
void loop(void) {
p = analogRead(potmeterPin); // get value from potmeter
w = map(p,0,1023,0,100); // map it between 0 and 100
// m = map(p,0,1023,0,90); // map needle movement
m = map(p,0,1023,180,0);
// show needle and dial
xx = m; // 135 = zero position, 180 = just before middle, 0 = middle, 45 = max
if (xx<45){
// positie correctie
xx=xx+135;
}
else {
xx=xx-45;
}
// picture loop
{
u8g.firstPage();
do {
// gauge(xx);
gauge(m); // changed by MGM
}
while( u8g.nextPage() );
}
}