传感技术
直播中

郝喜

9年用户 16经验值
擅长:连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计 模拟技术 连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计 EMC/EMI设计 连接器,EMC/MEI设计,EDA/IC设计 嵌入式技术 连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计 接口/总线/驱动 连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计 控制/MCU 连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计 连接器,EMC/MEI设计,EDA/IC设计
私信 关注
[经验]

【罗姆传感器评估板试用体验连载】之五 ——基于ARDUINO和传感器BM1390GLV的压力开关设计

       作为完结篇,本帖试图完成以下目标:利用内置I2C总线且具有防水功能的压力传感器,配备简单人机接口,根据检测压力值执行相应动作。这些部件可以组成液位开关或呼吸机压力检测及控制的功能原型。为此,我们基于ARDUINO和ROHM的BM1390GLV作为主控和传感器,加入0.96”的OLED屏,按键及继电器,组成了一个简单的压力开关。(图1)
系统框图.png
图1
       显然,在之前的试用中我们已经有了主控器和传感器,还有OLED屏,但不幸的是由于疫情居家隔离,设计图中的按键和继电器并不在工具箱里,为了将项目的检测控制过程可视化,找到了红绿LED灯并将其焊在了一块废PCB上,作为压力正常和超限报警的指示(图2)。抱歉做了改动和简化,但它的价值原本就在于探讨BM1390GLV作为压力传感器的应用可能,管中窥豹,引导聪明的电子发烧友们了解传感器的魅力并拓展出更多更丰富的应用场景。
led灯.jpg
图2
      将BM1390GLV传感器插入传感器扩展板的I2C接口,而扩展板和ARDUINO也通过排针排母连接好,按照图1指示用杜邦线连接OLED屏和红绿LED灯。如此,一个简陋但包括了输入输出且有显示功能的压力开关出现了。(图3)
整体效果.jpg
图3
      接着就是软件部分了。程序中主要包括传感器和OLED的驱动,本人编程水平实在low,但受共享开放的开源精神鼓舞,把主要部分源码摘录,如果能给网友一点点帮助,实属荣幸。
  1. //******************************************************************************/  
  2. //本程序仅供交流学习使用
  3. //  版 本 号   : v1.0
  4. //  作    者   : BRUCEHAO
  5. //  生成日期   : 2022-3-20
  6. //  功能描述   : 基于ARDUINO的采用BM1390GLV-Z压力传感器带OLED显示的压力指示开关
  7. //              说明:
  8. //              0.96OLED屏SPI接口:GND-电源地 VCC-5v D0-13 D1-11 RES-8 DC-9 CS-10              
  9. //              BM1390GLV-Z连接传感器扩展板J5 I2C接口
  10. //******************************************************************************/
  11. #include
  12. #include
  13. #include
  14. #include
  15. #include "oledfont.h"

  16. #define SYSTEM_BAUDRATE (9600)
  17. #define SYSTEM_WAIT     (200)       // ms
  18. #define ALARM           (1017)      //hpa

  19. BM1390GLV bm1390glv;

  20. #define scl 13  //SCLK
  21. #define sda 11  //MOSI
  22. #define res 8 //RES
  23. #define dc 9  //DC
  24. #define cs 10  //CS
  25. #define red 6  //红灯
  26. #define green 7  //绿灯

  27. #define OLED_SCL_Clr() digitalWrite(scl,LOW)//SCL
  28. #define OLED_SCL_Set() digitalWrite(scl,HIGH)

  29. #define OLED_SDA_Clr() digitalWrite(sda,LOW)//SDA
  30. #define OLED_SDA_Set() digitalWrite(sda,HIGH)

  31. #define OLED_RES_Clr() digitalWrite(res,LOW)//RES
  32. #define OLED_RES_Set() digitalWrite(res,HIGH)

  33. #define OLED_DC_Clr()  digitalWrite(dc,LOW)//DC
  34. #define OLED_DC_Set()  digitalWrite(dc,HIGH)
  35.          
  36. #define OLED_CS_Clr()  digitalWrite(cs,LOW)//CS
  37. #define OLED_CS_Set()  digitalWrite(cs,HIGH)

  38. #define LED_RED_ON()   digitalWrite(red,LOW)//red
  39. #define LED_RED_OFF()  digitalWrite(red,HIGH)

  40. #define LED_GREEN_ON()  digitalWrite(green,LOW)//green
  41. #define LED_GREEN_OFF() digitalWrite(green,HIGH)

  42. #define OLED_CMD  0  //写命令
  43. #define OLED_DATA 1 //写数据

  44. void setup()
  45. {
  46.     int32_t result;

  47.     Serial.begin(SYSTEM_BAUDRATE);
  48.     while (!Serial) {
  49.     }
  50.     Wire.begin();

  51.     result = bm1390glv.init();
  52.     if (result == BM1390GLV_COMM_OK) {
  53.         (void)bm1390glv.start();
  54.     }

  55.    OLED_Init();
  56.    OLED_ColorTurn(0);//0正常显示 1反色显示
  57.    OLED_DisplayTurn(0);//0正常显示 1翻转180度显示
  58.    OLED_Clear();


  59. }

  60. void loop()
  61. {
  62.     int32_t result;
  63.     float32 press, temp;

  64.     result = bm1390glv.get_val(&press, &temp);
  65.     if (result == BM1390GLV_COMM_OK) {
  66.         (void)Serial.write("Pressure(hPa):Temperature(degree Celsius) = ");
  67.         (void)Serial.print(press);
  68.         (void)Serial.write(", ");
  69.         (void)Serial.print(temp);
  70.         (void)Serial.println();
  71.     }

  72.     OLED_ShowChinese(16,0,0,16);//电
  73.     OLED_ShowChinese(34,0,1,16);//子
  74.     OLED_ShowChinese(52,0,2,16);//发
  75.     OLED_ShowChinese(70,0,3,16);//烧
  76.     OLED_ShowChinese(88,0,4,16);//友
  77.     OLED_ShowString(26,2,"BM1390GLV",16);
  78.     OLED_ShowString(8,4,"Pressure:",16);
  79.     OLED_ShowNum(48,6,press,4,16);
  80.     OLED_ShowString(88,6,"hPa",16);
  81.     if (press
  82.       LED_RED_OFF(); }   
  83.     else{ LED_RED_ON();
  84.       LED_GREEN_OFF();}
  85.     delay(SYSTEM_WAIT);
  86.     return;

  87. }

  88. //OLED的初始化
  89. void OLED_Init(void)
  90. {
  91.   pinMode(red,OUTPUT);//设置数字6
  92.   pinMode(green,OUTPUT);//设置数字7
  93.   pinMode(scl,OUTPUT);//设置数字8
  94.   pinMode(sda,OUTPUT);//设置数字9
  95.   pinMode(res,OUTPUT);//设置数字10
  96.   pinMode(dc,OUTPUT);//设置数字11
  97.   pinMode(cs,OUTPUT);//设置数字12
  98.   SPCR=(1<
  99.   OLED_RES_Clr();
  100.   delay(200);
  101.   OLED_RES_Set();
  102.   
  103.   OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
  104.   OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
  105.   OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
  106.   OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
  107.   OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
  108.   OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
  109.   OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
  110.   OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
  111.   OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
  112.   OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
  113.   OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
  114.   OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
  115.   OLED_WR_Byte(0x00,OLED_CMD);//-not offset
  116.   OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
  117.   OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
  118.   OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
  119.   OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  120.   OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
  121.   OLED_WR_Byte(0x12,OLED_CMD);
  122.   OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
  123.   OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
  124.   OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
  125.   OLED_WR_Byte(0x02,OLED_CMD);//
  126.   OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
  127.   OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
  128.   OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
  129.   OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
  130.   OLED_Clear();
  131.   OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
  132. }
  133. void OLED_ColorTurn(u8 i)
  134. {
  135.   if(!i) OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
  136.   else  OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
  137. }

  138. //屏幕旋转180度
  139. void OLED_DisplayTurn(u8 i)
  140. {
  141.   if(i==0)
  142.     {
  143.       OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
  144.       OLED_WR_Byte(0xA1,OLED_CMD);
  145.     }
  146. else
  147.     {
  148.       OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
  149.       OLED_WR_Byte(0xA0,OLED_CMD);
  150.     }
  151. }
  152. //写入一个字节
  153. void OLED_WR_Byte(u8 dat,u8 cmd)
  154. {  
  155.   u8 i;      
  156.   if(cmd)
  157.     OLED_DC_Set();
  158.   else
  159.     OLED_DC_Clr();      
  160.   OLED_CS_Clr();
  161.   
  162.   SPDR=dat;
  163.   while(!(SPSR&(1<
  164.   
  165.   OLED_CS_Set();
  166.   OLED_DC_Set();      
  167. }

  168. //坐标设置
  169. void OLED_Set_Pos(u8 x, u8 y)
  170. {
  171.   OLED_WR_Byte(0xb0+y,OLED_CMD);
  172.   OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
  173.   OLED_WR_Byte((x&0x0f),OLED_CMD);
  174. }      
  175. //开启OLED显示   
  176. void OLED_Display_On(void)
  177. {
  178.   OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
  179.   OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
  180.   OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
  181. }
  182. //关闭OLED显示     
  183. void OLED_Display_Off(void)
  184. {
  185.   OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
  186.   OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
  187.   OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
  188. }            
  189. //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!   
  190. void OLED_Clear(void)  
  191. {  
  192.   u8 i,n;      
  193.   for(i=0;i<8;i++)  
  194.   {  
  195.     OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
  196.     OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
  197.     OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
  198.     for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
  199.   } //更新显示
  200. }


  201. //在指定位置显示一个字符
  202. //x:0~127
  203. //y:0~63         
  204. //sizey:选择字体 6x8  8x16
  205. void OLED_ShowChar(u8 x,u8 y,const u8 chr,u8 sizey)
  206. {      
  207.   u8 c=0,sizex=sizey/2,temp;
  208.   u16 i=0,size1;
  209.   if(sizey==8)size1=6;
  210.   else size1=(sizey/8+((sizey%8)?1:0))*(sizey/2);
  211.   c=chr-' ';//得到偏移后的值
  212.   OLED_Set_Pos(x,y);
  213.   for(i=0;i
  214.   {
  215.     if(i%sizex==0&&sizey!=8) OLED_Set_Pos(x,y++);
  216.     if(sizey==8)
  217.     {
  218.       temp=pgm_read_byte(&asc2_0806[c][i]);
  219.       OLED_WR_Byte(temp,OLED_DATA);//6X8字号
  220.     }
  221.     else if(sizey==16)
  222.     {
  223.       temp=pgm_read_byte(&asc2_1608[c][i]);
  224.       OLED_WR_Byte(temp,OLED_DATA);//8x16字号
  225.     }
  226.     else return;
  227.   }
  228. }
  229. //m^n函数
  230. u32 oled_pow(u8 m,u8 n)
  231. {
  232.   u32 result=1;  
  233.   while(n--)result*=m;   
  234.   return result;
  235. }         
  236. //显示数字
  237. //x,y :起点坐标
  238. //num:要显示的数字
  239. //len :数字的位数
  240. //sizey:字体大小      
  241. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 sizey)
  242. {           
  243.   u8 t,temp,m=0;
  244.   u8 enshow=0;
  245.   if(sizey==8)m=2;
  246.   for(t=0;t
  247.   {
  248.     temp=(num/oled_pow(10,len-t-1))%10;
  249.     if(enshow==0&&t<(len-1))
  250.     {
  251.       if(temp==0)
  252.       {
  253.         OLED_ShowChar(x+(sizey/2+m)*t,y,' ',sizey);
  254.         continue;
  255.       }else enshow=1;
  256.     }
  257.     OLED_ShowChar(x+(sizey/2+m)*t,y,temp+'0',sizey);
  258.   }
  259. }
  260. //显示一个字符号串
  261. void OLED_ShowString(u8 x,u8 y,const char *chr,u8 sizey)
  262. {
  263.   u8 j=0;
  264.   while (chr[j]!='\0')
  265.   {   
  266.     OLED_ShowChar(x,y,chr[j++],sizey);
  267.     if(sizey==8)x+=6;
  268.     else x+=sizey/2;
  269.   }
  270. }
  271. //显示汉字
  272. void OLED_ShowChinese(u8 x,u8 y,const u8 no,u8 sizey)
  273. {
  274.   u16 i,size1=(sizey/8+((sizey%8)?1:0))*sizey;
  275.   u8 temp;
  276.   for(i=0;i
  277.   {
  278.     if(i%sizey==0) OLED_Set_Pos(x,y++);
  279.     if(sizey==16)
  280.     {
  281.       temp=pgm_read_byte(&Hzk[no][i]);
  282.       OLED_WR_Byte(temp,OLED_DATA);//16x16字号
  283.     }
  284. //    else if(sizey==xx) OLED_WR_Byte(xxx[c][i],OLED_DATA);//用户添加字号
  285.     else return;
  286.   }      
  287. }


  288. //显示图片
  289. //x,y显示坐标
  290. //sizex,sizey,图片长宽
  291. //BMP:要显示的图片
  292. void OLED_DrawBMP(u8 x,u8 y,u8 sizex, u8 sizey,const u8 BMP[])
  293. {   
  294.   u16 j=0;
  295.   u8 i,m,temp;
  296.   sizey=sizey/8+((sizey%8)?1:0);
  297.   for(i=0;i
  298.   {
  299.     OLED_Set_Pos(x,i+y);
  300.     for(m=0;m
  301.     {      
  302.        temp=pgm_read_byte(&BMP[j++]);
  303.        OLED_WR_Byte(temp,OLED_DATA);     
  304.     }
  305.   }
  306. }

      程序上传运行后,打开串口监视器,输出当前压力值和温度值。(图4)
IED-串口监视器.png
图4
      关于压力传感器的测试,来自ROHM官网BM1390GLV的测试视频截图显示,将BM1390GLV放在密闭且有水淹没传感器的罐子里面,随着针筒的上下移动,压力变化在笔记本电脑上直观地显示出来。(图5)
罗姆测试.png
图5
       碍于条件所限和项目设定,这里以压力值比较阀值方式控制输出指示,大于阀值红灯亮,否则绿灯亮(见文底视频)。而改变压力采取了用吸管对着传感器上方吹的方式,虽原始但有效,某种程度也验证了传感器的防水效果。
       自收到传感器评估套件月余,经历了一番特别的体验,第一次接触ARDUINO,第一次使用ROHM传感器,第一次在电子发烧友网发帖,而最后这张帖子也是在第一次居家隔离中完成的。敲完最后一行文字,就像结束了一段旅程,开心、疲惫、遗憾、不舍,然而对传感器世界的探索,还在继续……

test

更多回帖

发帖
×
20
完善资料,
赚取积分