当前位置: 首页 > news >正文

Arduino+数码管 = 量电压 | A+B problem | alphabet

材料

Arduino UNO R3、8041AS 七位数码管、若干导线、电阻、电位器、按钮、面包板。

量电压

A0 读入电压值,然后显示到数码管上即可。

voltage-display.ino
// https://www.lanpade.com/7-segment-led-dot-matrix/8041as.html// === Pin Definitions ===
// Segments (a,b,c,d,e,f,g,dp) -> Arduino digital pins
const int segPins[8] = {3, 7, 11, 9, 8, 4, 12, 10};
// Digits (D1–D4, common cathode) -> Arduino pins
const int digitPins[4] = {2, 5, 6, 13};// Segment map for numbers 0–9 (abcdefg, dp separate)
const byte numbers[10] = {B11111100, // 0B01100000, // 1B11011010, // 2B11110010, // 3B01100110, // 4B10110110, // 5B10111110, // 6B11100000, // 7B11111110, // 8B11110110  // 9
};float voltage = 0.0; // measured voltage// === Functions ===
void displayVoltage(float val) {// Scale value: 0.000–5.000 -> up to 5000 (int)int scaled = (int)(val * 1000);int digits[4];for (int i = 3; i >= 0; i--) {digits[i] = scaled % 10;scaled /= 10;}// Multiplex displayfor (int d = 0; d < 4; d++) {digitalWrite(digitPins[d], LOW); // enable digit// set segmentsfor (int s = 0; s < 8; s++) {bool on = bitRead(numbers[digits[d]], 7 - s);digitalWrite(segPins[s], on ? HIGH : LOW);}// Add decimal point after first digit (x.xxx)if (d == 0) digitalWrite(segPins[7], HIGH); // dp ON for digit 1else digitalWrite(segPins[7], LOW);delay(3);digitalWrite(digitPins[d], HIGH); // disable digit}
}void setup() {for (int i = 0; i < 8; i++) pinMode(segPins[i], OUTPUT);for (int i = 0; i < 4; i++) {pinMode(digitPins[i], OUTPUT);digitalWrite(digitPins[i], HIGH); // all off initially}
}void loop() {// Read analog input (0–5V → 0–1023)int adcValue = analogRead(A0);voltage = (adcValue * 5.0) / 1023.0;// Refresh display continuouslydisplayVoltage(voltage);
}

可以进一步地,输出到 Serial,并取最近 \(10\) 次结果取平均值,以稳定测量结果。

voltage-display.ino
// https://www.lanpade.com/7-segment-led-dot-matrix/8041as.html// === Pin Definitions ===
// Segments (a,b,c,d,e,f,g,dp) -> Arduino digital pins
const int segPins[8] = {3, 7, 11, 9, 8, 4, 12, 10};
// Digits (D1–D4, common cathode) -> Arduino pins
const int digitPins[4] = {2, 5, 6, 13};// Segment map for numbers 0–9 (abcdefg, dp separate)
const byte numbers[10] = {B11111100, // 0B01100000, // 1B11011010, // 2B11110010, // 3B01100110, // 4B10110110, // 5B10111110, // 6B11100000, // 7B11111110, // 8B11110110  // 9
};// === Functions ===
void displayVoltage(float val)
{// Scale value: 0.000–5.000 -> up to 5000 (int)int scaled = (int)(val * 1000);int digits[4];for (int i = 3; i >= 0; i--){digits[i] = scaled % 10;scaled /= 10;}// Multiplex displayfor (int d = 0; d < 4; d++){digitalWrite(digitPins[d], LOW); // enable digit// set segmentsfor (int s = 0; s < 8; s++){bool on = bitRead(numbers[digits[d]], 7 - s);digitalWrite(segPins[s], on ? HIGH : LOW);}// Add decimal point after first digit (x.xxx)if (d == 0)digitalWrite(segPins[7], HIGH); // dp ON for digit 1elsedigitalWrite(segPins[7], LOW);delay(3);digitalWrite(digitPins[d], HIGH); // disable digit}
}const int NUM_SAMPLES = 10;
int samples[NUM_SAMPLES];
int sampleIndex = 0;
bool bufferFilled = false;void setup()
{for (int i = 0; i < 8; i++)pinMode(segPins[i], OUTPUT);for (int i = 0; i < 4; i++){pinMode(digitPins[i], OUTPUT);digitalWrite(digitPins[i], HIGH); // all off initially}pinMode(A0, INPUT);Serial.begin(115200);for (int i = 0; i < NUM_SAMPLES; i++){samples[i] = 0;}
}void loop()
{// Read analog input (0–5V → 0–1023)int adcValue = analogRead(A0);samples[sampleIndex] = adcValue;sampleIndex++;if (sampleIndex >= NUM_SAMPLES){sampleIndex = 0;bufferFilled = true;}float result = 0.0;int total = bufferFilled ? NUM_SAMPLES : sampleIndex;for (int i = 0; i < total; i++){result += samples[i];}result *= 5. / 1023.;result /= total;Serial.print("Sensor reading: ");Serial.print(adcValue);Serial.print(" Voltage: ");Serial.print((float)adcValue * 5. / 1023., 3);Serial.print(" Average: ");Serial.println(result, 3);// Refresh display continuouslydisplayVoltage(result);
}

voltage-display

A+B problem

让我们先把操作数码管的代码简单封装一下,可以得到以下并不标准的 segment.cpp

segment.cpp
#ifndef SEGMENT_H_
#define SEGMENT_H_// https://www.lanpade.com/7-segment-led-dot-matrix/8041as.html// === Pin Definitions ===
// Segments (a,b,c,d,e,f,g,dp) -> Arduino digital pins
const int segPins[8] = { 3, 7, 11, 9, 8, 4, 12, 10 };
// Digits (D1–D4, common cathode) -> Arduino pins
const int digitPins[4] = { 2, 5, 6, 13 };// Segment map for numbers 0–9 (abcdefg, dp separate)
const byte numbers[10] = {B11111100,  // 0B01100000,  // 1B11011010,  // 2B11110010,  // 3B01100110,  // 4B10110110,  // 5B10111110,  // 6B11100000,  // 7B11111110,  // 8B11110110   // 9
};
// Segment map for alphas a-z
const unsigned char alphas[26] = {0xee, 0x3e, 0x9c, 0x7a, 0x9e, 0x8e, 0xbc, 0x6e, 0xf0, 0x70,0xae, 0x1c, 0xec, 0x2a, 0x3a, 0xce, 0xe6, 0x8c, 0x92, 0x1e,0x7c, 0x38, 0x7e, 0x26, 0x76, 0x5a
};const unsigned long stayMillis = 3;
const unsigned long BATCHMILLIS = 500;  // time for show four characters
const int strBufSize = 256;const int shockShowMillis = 200;
const int shockHideMillis = 200;byte getPattern(char c, bool dp) {byte pattern = 0;if (c >= '0' && c <= '9') {pattern = numbers[c - '0'];} else if (c >= 'A' && c <= 'Z') {pattern = alphas[c - 'A'];} else if (c >= 'a' && c <= 'z') {pattern = alphas[c - 'a'];}if (dp) {pattern |= B00000001;}return pattern;
}void showSingle(byte pattern, int digit) {if (!pattern) {delay(stayMillis);return;}digitalWrite(digitPins[digit], LOW);for (int i = 0; i < 8; i++) {digitalWrite(segPins[i], bitRead(pattern, 7 - i));}delay(stayMillis);digitalWrite(digitPins[digit], HIGH);
}int initStrDP(const char *str, const bool *DP, char *strBuf, bool *dpBuf) {int bufLen = 0, strLen = strlen(str);for (int i = 0; i < strLen; i++) {if (str[i] == '.') {if (bufLen > 0 && !dpBuf[bufLen - 1]) {dpBuf[bufLen - 1] = true;} else {strBuf[bufLen] = ' ';dpBuf[bufLen] = true;bufLen++;}} else {strBuf[bufLen] = str[i];dpBuf[bufLen] = DP != NULL ? DP[i] : false;bufLen++;}}strBuf[bufLen] = '\0';return bufLen;
}struct displayLoopStateNode {char strBuf[strBufSize];bool dpBuf[strBufSize];int bufLen;unsigned long totalMillis;unsigned long batchMillis;unsigned long start;unsigned long startBatch;int currentRound;int totalRounds;bool active;
} _displayLoopState;void displayLoopTaskInit(const char *str, const bool *DP = NULL, unsigned long totalMillis = 1000, unsigned long batchMillis = BATCHMILLIS) {int strLen = strlen(str);if (str == NULL || strLen == 0) return;_displayLoopState.bufLen = initStrDP(str, DP, _displayLoopState.strBuf, _displayLoopState.dpBuf);_displayLoopState.totalRounds = _displayLoopState.bufLen + 4;_displayLoopState.batchMillis = batchMillis;_displayLoopState.totalMillis = totalMillis;unsigned long requiredTotal = _displayLoopState.totalRounds * batchMillis;if (requiredTotal > totalMillis) {_displayLoopState.batchMillis = totalMillis / _displayLoopState.totalRounds;}_displayLoopState.start = millis();_displayLoopState.startBatch = _displayLoopState.start;_displayLoopState.currentRound = 0;_displayLoopState.active = true;
}// return a bool, false for task ended
bool displayLoopTaskUpdate() {if (!_displayLoopState.active) {return false;}if (millis() - _displayLoopState.start >= _displayLoopState.totalMillis) {_displayLoopState.active = false;return false;}for (int digit = 0; digit < 4; digit++) {int charPos = _displayLoopState.currentRound - 3 + digit;char displayChar = ' ';bool displayDP = false;if (0 <= charPos && charPos < _displayLoopState.bufLen) {displayChar = _displayLoopState.strBuf[charPos];displayDP = _displayLoopState.dpBuf[charPos];}byte pattern = getPattern(displayChar, displayDP);showSingle(pattern, digit);}unsigned long currentTime = millis();while (currentTime - _displayLoopState.startBatch >= (_displayLoopState.currentRound + 1) * _displayLoopState.batchMillis) {_displayLoopState.currentRound++;if (_displayLoopState.currentRound >= _displayLoopState.totalRounds) {_displayLoopState.currentRound = 0;_displayLoopState.startBatch = currentTime;}}return true;
}/*** 在四位数码管上滚动显示字符串* @param str 要显示的字符串* @param DP 小数点控制数组,与 str 等长* @param totalMillis 总显示时间(毫秒)* @param batchMillis 每四个字符的显示时间(毫秒)*/
void displayLoop(const char *str, const bool *DP = NULL, unsigned long totalMillis = 1000, unsigned long batchMillis = BATCHMILLIS) {displayLoopTaskInit(str, DP, totalMillis, batchMillis);while (!displayLoopTaskUpdate())continue;
}void display(int value, unsigned int DP = B0000) {int digits[4];for (int i = 3; i >= 0; i--) {digits[i] = value % 10;value /= 10;}// Multiplex displayfor (int d = 0; d < 4; d++) {byte pattern = getPattern('0' + digits[d], DP & B1 << d ? true : false);showSingle(pattern, d);}
}void display(const char* str, unsigned DP = B0000) {for (int d = 0; d < 4; d++) {byte pattern = getPattern(str[d], DP & B1 << d ? true : false);showSingle(pattern, d);}
}#define __define_displayForMillis(TYPE) \void displayForMillis(TYPE value, unsigned int DP = B0000, unsigned long millisCount = 1000) { \unsigned long start = millis(); \while (millis() - start < millisCount) { \display(value, DP); \} \}
__define_displayForMillis(int)
__define_displayForMillis(const char*)
#undef __define_displayForMillis#define __define_displayShock(TYPE) \void displayShock(TYPE value, unsigned int DP = B0000, unsigned long millisCount = 1000) { \unsigned long start = millis(); \while (millis() - start < millisCount) { \displayForMillis(value, DP, min(millisCount - (millis() - start), shockShowMillis)); \delay(shockHideMillis); \} \}
__define_displayShock(int)
__define_displayShock(const char*)
#undef __define_displayShockvoid segmentInit() {for (int i = 0; i < 8; i++)pinMode(segPins[i], OUTPUT);for (int i = 0; i < 4; i++) {pinMode(digitPins[i], OUTPUT);digitalWrite(digitPins[i], HIGH);  // all off initially}
}#endif

于是可以方便地写出如下程序:

aplusb.ino
#include "include/segment.cpp"const int inputScale = 5;
const int inputPin = A0;
const int buttonPin = A1;int readInt() {while (true) {int raw = analogRead(inputPin);int value = raw / inputScale;display(value);if (digitalRead(buttonPin) == HIGH) {displayForMillis(value, 0, 20);while (digitalRead(buttonPin) == HIGH) {display(value);}displayShock(value);return value;}}
}void setup() {segmentInit();pinMode(inputPin, INPUT);pinMode(buttonPin, INPUT);Serial.begin(115200);
}void SerialPrintf(const char *fmt, ...) {char buf[128];va_list args;va_start(args, fmt);vsnprintf(buf, sizeof(buf), fmt, args);va_end(args);Serial.print(buf);
}void loop() {int a = readInt();SerialPrintf("Read a = %d\n", a);int b = readInt();SerialPrintf("Read b = %d\n", b);int sum = a + b;SerialPrintf("%d + %d = %d\n", a, b, sum);displayForMillis(sum, B0111, 5000);
}

aplusb

alphabet

我们已经封装好了,直接用就行了。

alphabet.ino
#include "include/segment.cpp"void setup() {segmentInit();displayLoop(".0123456789.A...BCDEFGHIJKLMNOPQRSTUVWXYZ", NULL, 5000);displayLoop("520", NULL, 5000);displayLoop("520 1314", NULL, 8000);displayLoop("i love you", NULL, 8000);displayForMillis(" ADD", 0, 1000);displayShock("F  K", 0, 3000);displayLoopTaskInit("F  K YOU", NULL, 5000);
}void loop() {if (digitalRead(A1) == HIGH) {while (digitalRead(A1) == HIGH)continue;displayShock("F  K", 0, 3000);}if (!displayLoopTaskUpdate()) {displayLoopTaskInit("F  K ME. PLEASE", NULL, 5000);}
}

接线同 aplusb。

http://www.hskmm.com/?act=detail&tid=24107

相关文章:

  • 详细介绍:【数据库知识】TxSQL 主从数据库同步底层原理深度解析
  • 2025.10.3 NOIP 模拟赛
  • Python 之操作excel
  • 国家生物信息数据下载
  • linux jenkins服务启动异常等,排查是否日志磁盘空间满 du df命令
  • 详细介绍:LeetCode 391 完美矩形
  • [NOI2025] 集合 题解
  • bi数据报表发送周期,周报和月报获取日期时间
  • 技术Leader的1-3-5沟通法则:向上管理的艺术 - 指南
  • cannot resolve method add in T 及 T 泛型类型生成Excel文件,区别是数据Model不同
  • 测试环境elasticSearch数据泄露排查
  • 深入解析:Spring boot中 限制 Mybatis SQL日志的大字段输出
  • 【AI时代速通QT】第九节:揭秘Qt编译全流程-从.pro材料到可执行程序
  • 考试心得5
  • javascript高级 - Ref
  • Solar9月赛wp - 场
  • 实用指南:深度解析Sora2:技术革命与创意产业的未来图景
  • 自动化安全工具的双刃剑:红队演练揭示安全响应盲区
  • Elastic Search 安装部署最全教程(Docker)
  • 详细介绍:图像分割:PyTorch从零开始实现SegFormer语义分割
  • 深入解析:Playwright同步、异步、并行、串行执行效率比较
  • 2025十一集训——Day2模拟赛
  • 2025十一集训——Day模拟赛
  • Qt纯代码实现智能安防集中管理平台/楼宇对讲管理系统/门禁管理/视频监控
  • 汉文博士词典库源文件已在 github 开放
  • 读人形机器人30未来20年
  • Flutter + Ollama:开启本地AI的全平台新纪元 —— 从零剖析一款现代化AI客户端的技能奥秘
  • 股票资料API接口全解析:从技术原理到多语言实战(含实时行情、MACD、KDJ等技术指标数据与API文档详解)
  • 产业园区招商团队快躺平了 - 智慧园区
  • 洛谷 P3545