Arduino网络编程实战-从SD卡加载图像数据并显示

从SD卡加载图像数据并显示

JSON(JavaScript Object Notation)是一种开放的标准文件格式和数据交换格式,它使用人类可读的文本来存储和传输由属性-值对和数组(或其他可序列化值)组成的数据对象。 它是一种常见的数据格式,在电子数据交换中具有多种用途,包括带有服务器的 Web 应用程序。

JSON 是一种独立于语言的数据格式。 它源自 JavaScript,但许多现代编程语言都包含生成和解析 JSON 格式数据的代码。 JSON 文件名使用扩展名 .json。当数据从服务器发送到网页时,通常使用 JSON。JSON是“自我描述的”并且易于理解。

ArduinoJson库为嵌入式系统提供了高性能的JSON数据序列化和反序列化支持。

前面的文章对Arduino中JSON数据解析做出详细的介绍,请参考:

SD卡模块对于需要数据记录的项目特别有用。前面的文章对Arduino如何使用SD卡做了详细的介绍,请参考:

本次实例将演示如何从SD卡加载图像数据并使用SSD1306 OLED显示。

1、硬件准备

  • Arduino Mega2560 开发板一块
  • SD卡模块一个及SD卡一个
  • SSD1306 OLED屏幕一块
  • 数据线一条
  • 杜邦线若干

硬件接线,请关于前面相关文章,在这里不再做描述。

2、软件准备

3、JSON储存图像数据说明

本次实例储存图像数据的JSON格式如下(在这里文件名为:1@1x.json,并保存在SD卡根目录下):

1
2
3
4
5
6
{
width:32,
height:32,
datas:[0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 8, 24, 24, 0, 12, 0, 56, 0, 6, 0, 112, 0, 2, 126, 32, 0, 0, 231, 0, 0, 1, 193, 128, 0, 0, 0, 192, 0, 28, 0, 192, 0, 255, 128, 79, 1, 193, 192, 79, 3, 128, 96, 192, 7, 0, 49, 192, 30, 0, 49, 128, 60, 0, 24, 0, 96, 0, 28, 96, 192, 0, 6, 48, 192, 0, 3, 24, 192, 0, 3, 0, 194, 2, 3, 0, 198, 6, 3, 0, 102, 102, 102, 0, 100, 68, 78, 0, 12, 204, 204, 0, 12, 204, 192, 0, 8, 136, 128, 0, 25, 153, 128, 0, 17, 145, 128, 0, 3, 3, 0, 0, 3, 3, 0, 0],
}

通过前面的OLED显示图片实例制作图像数据方式可以得到如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const unsigned char epd_bitmap_105_sun_shower [] PROGMEM = {
0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x08, 0x18, 0x18,
0x00, 0x0c, 0x00, 0x38, 0x00, 0x06, 0x00, 0x70, 0x00, 0x02, 0x7e, 0x20, 0x00, 0x00, 0xe7, 0x00,
0x00, 0x01, 0xc1, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x1c, 0x00, 0xc0, 0x00, 0xff, 0x80, 0x4f,
0x01, 0xc1, 0xc0, 0x4f, 0x03, 0x80, 0x60, 0xc0, 0x07, 0x00, 0x31, 0xc0, 0x1e, 0x00, 0x31, 0x80,
0x3c, 0x00, 0x18, 0x00, 0x60, 0x00, 0x1c, 0x60, 0xc0, 0x00, 0x06, 0x30, 0xc0, 0x00, 0x03, 0x18,
0xc0, 0x00, 0x03, 0x00, 0xc2, 0x02, 0x03, 0x00, 0xc6, 0x06, 0x03, 0x00, 0x66, 0x66, 0x66, 0x00,
0x64, 0x44, 0x4e, 0x00, 0x0c, 0xcc, 0xcc, 0x00, 0x0c, 0xcc, 0xc0, 0x00, 0x08, 0x88, 0x80, 0x00,
0x19, 0x99, 0x80, 0x00, 0x11, 0x91, 0x80, 0x00, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00
};

// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 144)
const int epd_bitmap_allArray_LEN = 1;
const unsigned char\* epd_bitmap_allArray[1] = {
epd_bitmap_105_sun_shower
};

由于ArduinoJson库不能将十六进制数字字符串转换为数字,因此需要转换。在这里通过Python脚本对图像进行转换,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
datas = [0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x08, 0x18, 0x18, 
0x00, 0x0c, 0x00, 0x38, 0x00, 0x06, 0x00, 0x70, 0x00, 0x02, 0x7e, 0x20, 0x00, 0x00, 0xe7, 0x00,
0x00, 0x01, 0xc1, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x1c, 0x00, 0xc0, 0x00, 0xff, 0x80, 0x4f,
0x01, 0xc1, 0xc0, 0x4f, 0x03, 0x80, 0x60, 0xc0, 0x07, 0x00, 0x31, 0xc0, 0x1e, 0x00, 0x31, 0x80,
0x3c, 0x00, 0x18, 0x00, 0x60, 0x00, 0x1c, 0x60, 0xc0, 0x00, 0x06, 0x30, 0xc0, 0x00, 0x03, 0x18,
0xc0, 0x00, 0x03, 0x00, 0xc2, 0x02, 0x03, 0x00, 0xc6, 0x06, 0x03, 0x00, 0x66, 0x66, 0x66, 0x00,
0x64, 0x44, 0x4e, 0x00, 0x0c, 0xcc, 0xcc, 0x00, 0x0c, 0xcc, 0xc0, 0x00, 0x08, 0x88, 0x80, 0x00,
0x19, 0x99, 0x80, 0x00, 0x11, 0x91, 0x80, 0x00, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00]

datas_int = [x for x in datas]
print(datas_int)

运行脚本后,得到如下结果:

1
2
[0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 8, 24, 24, 0, 12, 0, 56, 0, 6, 0, 112, 0, 2, 126, 32, 0, 0, 231, 0, 0, 1, 193, 128, 0, 0, 0, 192, 0, 28, 0, 192, 0, 255, 128, 79, 1, 193, 192, 79, 3, 128, 96, 192, 7, 0, 49, 192, 30, 0, 49, 128, 60, 0, 24, 0, 96, 0, 28, 96, 192, 0, 6, 48, 192, 0, 3, 24, 192, 0, 3, 0, 194, 2, 3, 0, 198, 6, 3, 0, 102, 102, 102, 0, 100, 68, 78, 0, 12, 204, 204, 0, 12, 204, 192, 0, 8, 136, 128, 0, 25, 153, 128, 0, 17, 145, 128, 0, 3, 3, 0, 0, 3, 3, 0, 0]

将上述数据添加到JSON文件中的datas字段即可。

4、代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <Wire.h>
#include <Adafruit\_GFX.h>
#include <Adafruit\_SSD1306.h>
#include <SdFat.h>
#include <ArduinoJson.h>

// 屏幕大小
#define SCREEN\_WIDTH 128 // OLED display width, in pixels
#define SCREEN\_HEIGHT 64 // OLED display height, in pixels

// 图片大小
#define IMG\_HEIGHT 32
#define IMG\_WIDTH 32

// OLED重置引脚,I2C时和与板载重置引脚共用时,设置-1
#define OLED\_RESET -1
// OLED地址
#define SCREEN\_ADDRESS 0x3C
// OLED对象
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// SD\_FAT\_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
// SD卡文件系统格式类型
#define SD\_FAT\_TYPE 0
// SD卡SPI的CS引脚
#define SD\_CS\_PIN 4
// SD卡时钟,如果不正常,请降低时钟频率
#define SPI\_CLOCK SD\_SCK\_MHZ(50)
// SD卡SPI配置
#define SD\_CONFIG SdSpiConfig(SD\_CS\_PIN, DEDICATED\_SPI, SPI\_QUARTER\_SPEED)
// 根据文件系统类型声明不SdFat对象和文件对象
#if SD\_FAT\_TYPE == 0
SdFat sd;
File file;
#elif SD\_FAT\_TYPE == 1
SdFat32 sd;
File32 file;
#elif SD\_FAT\_TYPE == 2
SdExFat sd;
ExFile file;
#elif SD\_FAT\_TYPE == 3
SdFs sd;
FsFile file;
#else // SD\_FAT\_TYPE
#error Invalid SD\_FAT\_TYPE
#endif // SD\_FAT\_TYPE

unsigned char img_datas [1024] = {0};
void setup() {
Serial.begin(9600);

// 初始化OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}

// 显示欢迎画面
// Clear the buffer Adafruit\_SSD1306.h文件中将 #define SSD1306\_NO\_SPLASH 打开屏蔽
display.display();
delay(1000);
// 清屏
display.clearDisplay();

Serial.println("Initializing SD card...");
// 初始化SD卡
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
return;
}
Serial.println("Initialized SD card...");

// 声明静态Json文档对象
StaticJsonDocument<2048> doc;
// 打开文件
if (!file.open("/1@1x.json", O_RDWR)) {
Serial.println("open failed");
while(true);
}
DeserializationError error = deserializeJson(doc, file);
if (error){
Serial.println(F("Failed to read file, using default configuration"));
file.close();
while(true);
}
int width = doc["width"].as<int>();
int height = doc["height"].as<int>();

for(int j = 0;j < 10;j++){
doc.clear();
Serial.println(image_files[j].c\_str());
if (!file.open(image_files[j].c\_str(), O_RDWR)) {
Serial.println("open failed");
while(true);
}
DeserializationError error = deserializeJson(doc, file);
int width = doc["width"].as<int>();
int height = doc["height"].as<int>();
// 查询图像数据大小
int len = doc["datas"].as<JsonArray>().size();
// 清空图像缓存
memset(img_datas,0,1024);
// 将JSON中图像数据复制到图像缓存中
for(int i = 0;i < len;i++){
img_datas[i] = doc["datas"][i].as<unsigned char>();
}
// 关闭文件
file.close();
// 显示图像
testdrawbitmap((uint8\_t\*)img_datas,width,height);
delay(500);
}
}

void loop() {
}

void testdrawbitmap(const uint8\_t\* datas,int width,int height) {
display.clearDisplay();
// 绘制图片
display.drawBitmap(
(display.width() - width ) / 2,
(display.height() - height) / 2,
datas, width, height, 1);
display.display();
delay(1000);
}

文章来源: https://iotsmart.blog.csdn.net/article/details/122999872