您尚未登录。

楼主 # 2024-06-25 09:08:18

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,363
积分: 1323.5

请教,单片机一般如何保存定时采集的数据,要求长期保存,方便查寻历史记录。

目前用d133定时采集can总线上的数据,然后在rgb屏幕上的lvgl界面上显示出来。

但是想保存采集到的数据,方便其他设备查询历史记录,或者在lvgl界面上查询历史记录。
请教,有什么好的办法?

问了几个群里,有推荐sqlite3和flashdb的。想知道,使用数据库有什么好处?

还有就是目前使用的spi nor flash,如果用fatfs,好想说并不适合频繁擦写。

目前有两种需求:
1, 采集can总线上定时发送过来的数据,每次保存,或几次采集后保存一次,可能保存频率很高;
2, 采集can总线上不定时发送过来的,一般是系统出现问题时才发送过来,保存频率较低。

最近编辑记录 Gentlepig (2024-06-25 09:23:01)

离线

楼主 #2 2024-06-25 09:32:40

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,363
积分: 1323.5

Re: 请教,单片机一般如何保存定时采集的数据,要求长期保存,方便查寻历史记录。

晕哥 说:

建议用日志型(ext4,jffs2...)的文件系统,按时间段分文件存储。

如果没有后备电池和断电检测,做好最后一个文件阵亡的心理准备。

我这不是linux系统啊,是rtt,目前看sdk里默认打开了fatfs和littlefs。

离线

楼主 #4 2024-06-25 17:37:37

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,363
积分: 1323.5

Re: 请教,单片机一般如何保存定时采集的数据,要求长期保存,方便查寻历史记录。

手头的板子没焊接sd相关,打算先用spi nor flash存储做个尝试。
rtt配置里勾选了littlefs和sqlte,sqlite里勾选了example。
/rodata配置为fatfs,分配了5M;/data配置为littlefs,分配了7M。

student_dao.c里默认数据库存在/data/stu_info.db。

编译后烧录到板子上,执行crate_student_tbl命令,按说应该在/data目录下生成stu_info.db数据库,可串口终端一直卡在这个命令这里,不过光标还是闪烁的。
等了几分钟后,仍是这个效果,就重启板子,发现/data下有stu_info.db文件,虽然大小为0。
执行stu命令,应该显示数据库所有数据,结果仍是卡住且光标正常闪烁。

以为是文件系统的问题,将student_dao.c里创建数据库的位值改为/rodata,这个是fatfs格式的。
结果执行create_student_tbl命令后,还是卡住,重启后,在/rodata目录下,并没有db数据库文件生成。

离线

楼主 #9 2024-06-26 09:26:13

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,363
积分: 1323.5

Re: 请教,单片机一般如何保存定时采集的数据,要求长期保存,方便查寻历史记录。

海石生风 说:

@Gentlepig
写一大串没用的,难道你就没有怀疑是你输入的命令有问题?写了一大串也没有把重要细节show出来!

输入命令如下:

dlk /> df /rodata                                                               
disk free: 4.8 MB [ 9968 block, 512 bytes per block ]                           
dlk /> df /data                                                                 
disk free: 6.8 MB [ 1764 block, 4096 bytes per block ]                          
dlk /> create_student_tbl                                                       
/rodata/stu_info.db

对应函数如下,无参数,目的是创建数据库:

static int create_student_tbl(void)
{
    int fd = 0;

    db_set_name("/data/stu_info.db");
    fd = open(db_get_name(), O_RDONLY);
    rt_kprintf(db_get_name());
    if (fd < 0)
    {
        /* there is not the .db file.create db and table */
        const char *sql = "CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);";
        return db_create_database(sql);
    }
    else if (db_table_is_exist("student") > 0)
    {
        /* there is the table int db.close the db. */
        close(fd);
        LOG_I("The table has already existed!\n");
        return RT_EOK;
    }
    else
    {
        /* there is not the table int db.create the table */
        const char *sql = "CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);";
        return db_create_database(sql);
    }
}
MSH_CMD_EXPORT(create_student_tbl, create sqlite db);

详细文件见:
https://gitee.com/artinchip/luban-lite/blob/master/packages/third-party/sqlite/student_dao.c

离线

楼主 #10 2024-06-26 14:46:12

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,363
积分: 1323.5

Re: 请教,单片机一般如何保存定时采集的数据,要求长期保存,方便查寻历史记录。

还是得看readme.

358 ## 注意事项
  1 - SQLite资源占用:RAM:250KB+,ROM:310KB+,所以需要有较充足的硬件资源。
  2 - 根据应用场景创建合理的表结构,会提高操作效率。
  3 - 根据应用场合理使用SQL语句,如查询条件,插入方式等。
  4 - 如涉及到多表操作或联表查询,最好使用PowerDesigner等工具合理设计表。

我是在msh里执行create_student_tbl命令的,应该是需要比较大的内存,而msh默认分配了4k内存,改成40k后,可以创建数据库成功了。使用stu add xxx命令来增加数据条出错了,还在解决:

dlk /> 
dlk /> cd data
dlk /data> ls
Directory /data:
123                 4                        
stu_info.db         12288                    
ui_font_Big.c       102408                   
dlk /data> stu add 1
01-01 08:31:52 E/app.dbhelper: bind failed errmsg:database disk image is malformed
01-01 08:31:52 E/app.dbhelper: db operator failed,rc=1
01-01 08:31:52 E/app.student_dao: add failed!
dlk /data> 

dbhelper.c文件里,该行报错:

268         sqlite3_finalize(stmt);
  1         if ((rc != SQLITE_OK) && (rc != SQLITE_DONE))
  2         {
  3             LOG_E("bind failed errmsg:%s", sqlite3_errmsg(db));
  4             goto __db_exec_fail;
  5         }

-------------------------------

msh栈空间改为400k,结果仍一样。
尝试改为1M,结果上电后,不运行了...

---------------------------------

student_dao.c里,执行stu add命令后,会调用到这个函数。

int student_add(rt_list_t *h)
{
    return db_nonquery_operator("insert into student(name,score) values (?,?);", student_insert_bind, h);
}

db_nonquery_operator()执行一系列操作后,调用的是如下函数。

static int student_insert_bind(sqlite3_stmt *stmt, int index, void *arg)
{
    int rc = 0;
    rt_list_t *h = arg, *pos, *n;
    student_t *s = RT_NULL;
    rt_list_for_each_safe(pos, n, h)
    {
        s = rt_list_entry(pos, student_t, list);
        sqlite3_reset(stmt);                                        //reset the stmt
        sqlite3_bind_text(stmt, 1, s->name, strlen(s->name), NULL); //bind the 1st data,is a string
        sqlite3_bind_int(stmt, 2, s->score);                        //bind the 1st data,is a int
        rc = sqlite3_step(stmt);                                    //execute the stmt by step
    }

    if (rc != SQLITE_DONE)
        return rc;
    return SQLITE_OK;
}

感觉是这个函数执行后返回的值rc,根据rc值执行了报错输出。

最近编辑记录 Gentlepig (2024-06-26 17:45:54)

离线

楼主 #13 2024-06-26 16:08:05

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,363
积分: 1323.5

Re: 请教,单片机一般如何保存定时采集的数据,要求长期保存,方便查寻历史记录。

感谢各位,板子是有网口的,目前是通过tcp将数据发送给局域网pc。

本机存储是想以后可能会用到,某些不定时的,数量较少的数据,希望存储到板子上。

离线

楼主 #16 2024-06-27 16:55:44

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,363
积分: 1323.5

Re: 请教,单片机一般如何保存定时采集的数据,要求长期保存,方便查寻历史记录。

https://club.rt-thread.org/ask/question/9faea7447d375649.html

这个sqlite在spi和sd卡上没法用,慢到无法忍受.归根结底是文件系统速度太慢.我有在uffs和yaffs文件系统上测,文件系统速度是上去了。但是数据量增加到一定量数据库就报SQL error: database disk image is malformed。不知道什么鬼。
但是在SD卡文件系统上测试就不会

在rtt论坛搜到同样报错的帖子,我还是放弃单片机上跑sqlite吧,或者等artinchip来解决。
话说,artinchip的lunban-lite sdk里带的这个sqlite,也许是给d21x这类片子运行的吧。

最近编辑记录 Gentlepig (2024-06-27 16:57:15)

离线

楼主 #18 2024-06-28 10:27:57

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,363
积分: 1323.5

Re: 请教,单片机一般如何保存定时采集的数据,要求长期保存,方便查寻历史记录。

莫名奇妙的例程能正常运行了。

dlk /data> create_student_tbl
/data/stu_info.dbdlk /data> 
dlk /data> ls
Directory /data:
stu_info.db         12288                    
dlk /data> stu add 10
Insert 10 record(s): 1166ms, speed: 116ms/record
dlk /data> stu
test get all students
id:1    name:Student44408       score:40
id:2    name:Student44409       score:41
id:3    name:Student44411       score:43
id:4    name:Student44414       score:46
id:5    name:Student44418       score:50
id:6    name:Student44423       score:55
id:7    name:Student44429       score:61
id:8    name:Student44436       score:68
id:9    name:Student44444       score:76
id:10   name:Student44453       score:85
record(s):10
dlk /data> stu score 40 60

-------------------------------------

创建数据库,新增数据、删除、按分数范围查找,都能执行。
执行stu score时有个坑,按说stu score 40 60,就可以查找40-60分数的数据,结果本来是4个参数,有个可选的第5个参数,程序里只判断参数大于4个的情况下,也会去读取第5个参数,结果就卡住了。加个条件即可,参数大于5时才读第5个参数。

msh线程分配了10k空间,占用率85%。

-------------------------------------

上午发现stu add命令可以成功执行后,觉得之前尝试给msh分配的空间太大了,就由512k逐渐减下去,减到10k后sqlite例程的几个命令还可以使用,以为没事了。
下午切到win下,又试着重新编译sdk里的sqlite,结果又出现了上次的问题,create_student_tbl命令可以成功创建数据库,但是stu add命令就会失败,仍报错:

bind failed errmsg:database disk image is malformed

msh线程空间也改大了,无效。怀疑是spi速度的原因影响spi nor flash里的littlefs分区的读写,降低spi速度,无效。

又切回到ubuntu下,由于下午想尝试libmodbus,重新编译过。发现ubuntu下编译烧录后,stu add命令也是报错。

最近编辑记录 Gentlepig (2024-06-28 17:13:46)

离线

楼主 #19 2024-06-29 11:47:11

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,363
积分: 1323.5

Re: 请教,单片机一般如何保存定时采集的数据,要求长期保存,方便查寻历史记录。

https://club.rt-thread.org/ask/question/9faea7447d375649.html
看这篇文章,发现需要打开SAL选项,估计是
enable bsd socket operated by file system api.
但是我搜目前的rtt组件,没搜到这个,目前打开的是:

  │ │                           [*] SAL: socket abstraction layer  --->                                                           │ │  
  │ │                           -*- Enable network interface device  --->   

而且,和local package里的lwip寸在冲突。

现在不用local lwip时,sqlite功能正常了。

-----------------------------------------------

一次插入8000条数据,可以成功,插入9000条,就卡住了,重启后发现目录下多了个journel.db。
删掉数据库,创新创建,多次插入8000调数据,可以成功,但发现插入一条数据的时间比插入8000调数据的时间还长。
比如,插入一条数据要16秒,插入8000调要12秒。
多次插入后,就出错了,用stu score再也无法查询出某范围的条数。复制数据到到pc,用db brower查看,也看到数据内容。
此时文件系统没有被占满,分配了7M空间,数据库才700多k。

------------------------------

删掉数据库,重新创建,然后每次只插入一条数据,发现时间大概话非1秒,有点难受啊。

用stu命令可以看到列出数据,看数据库最大条数是8564, 再新增也是这个数字。那么,数据库最大容量是8564?但实际不是,用stu score m n,可列出score值巍在m和n范围内的数据条,可以看的id有超过8664的。

最近编辑记录 Gentlepig (2024-06-29 16:24:10)

离线

楼主 #21 2024-07-24 14:47:37

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,363
积分: 1323.5

Re: 请教,单片机一般如何保存定时采集的数据,要求长期保存,方便查寻历史记录。

@海石生风
你的d21x也是运行的rtt还是linux?
按说d13x和d21x主频相比差不算太大。d13x 480M, d21x 504/600M.
剩下的,内存大小差异?8M不够用?新做了一版,打算试试16M的。

我插入9000条数据就卡死,但是连续插入8k条数据可以成功。最后放弃了sqlite这一方案。
后来尝试了flashdb。

想问下,nand flash,是不是就不用考虑擦写均衡了?
我看flashdb的几个例程,都是spi nor flash和onchip flash的。

最近编辑记录 Gentlepig (2024-07-24 14:53:59)

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn