开发板:orange pi  zero3

镜像:ubuntu-jammy

Q:解决异常重启造成Linux系统损坏的问题

A:将/etc/fstab中,根文件系统的载入方式改为只读,如下:

UUID=097c0934-864c-4961-9bf6-4ab53f3c5f5a / ext4 ro,defaults,noatime,commit=600,errors=remount-ro 0 1
tmpfs /tmp tmpfs defaults,nosuid 0 0

默认情况下,重启后会自动进入orangepi用户,因此,将要执行的程序放到~/.profile里,即可实现开机自动执行。这样异常重启后,不会对根文件系统造成任何伤害。

如果要改为rw模式,只需要mount -o rw,remount / 即可。

 

Q:等待网络完全联通,否则持续循环

rtn=5
while [ $rtn -ne 0 ]; do
   ping -c 1 www.baidu.com > /dev/null 2>&1
   rtn=$?
done

 

Q:GPIO手工操作

gpio  readall

GPIO列:GPIO编号

WPI: 当使用wiringpi进行编程时,使用的编号

Mode: IN/OUT

V: value, 高低电平指示(1-高 0-低)

手工操作GPIO电平:

  查看结果:注意26针角的value变为了1

 清楚操作:

echo 74 > unexport,完成后,gpio74目录将消失

 

Q: 利用wirringpi操作GPIO

orangepi zero3自带wiringpi,不需要安装

cd /usr/src/wiringOP/examples/ 这里是各种例程

以下是示例代码(GPIO部分主要参考blink相关例程)

include <wiringPi.h>

int main() {
 
      wiringPiSetup();          //初始化    
      pinMode (16, OUTPUT) ;   //设置wpi编号16的针角为OUTPUT模式
      digitalWrite (16, HIGH);    //设置为高电平
      digitalWrite (16, LOW);    //设置为低电平
}    

 

gitee/github的使用:

git config --global user.name 'peterhu318'
git config --global user.email 'peterhu318@126.com

 

clone iot项目:git clone https://gitee.com/peterhu318/iot.git

push iot项目:

cd ./iot

git add .

git commit -m "describe"

git push

 

串口通讯(serial)测试:

机器1:win11 + sscom5

机器2:orangepi zero3 + jammy  + minicom 串口pin: 8,10

先打开urlt 5,重启,在/dev/下能看到 ttyAS5,说明配置没问题了

 执行minicom会说找不到/dev/modem,只要链接一下设备即可。

进入minicom设置:minicom  -s进入设置:9600N8,1 一定不要设置硬件流控,否则会出现无法向win11发送情况。

总结来说:双方的参数设置一定要匹配,否则会出现一发能发,一方不能发。有一方发送乱码等各种情况。

当以上测试没有问题后,就可以上程序了。

wiringpi在/usr/src下有一个example的示例,里面有两个: serialRead及serialTest。只要改一下里面的设备名及波特率,就可以用make进行编译并测试了。

 

关于某些i2c设备(流量传感器)无法识别的问题:

posifa pmf83020流量传感器,用香橙派无法识别,但换成悟空派就能识别。

发现香橙派用的是5.x的内核版本,将其换成6.x的内核版本,就能够正确识别了。

 

关于香橙派启动慢的问题

启动下面时,总是要等大约20s左右,造成启动缓慢

Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.

Begin: Running /scripts/local-premount ... Scanning for Btrfs filesystems

解决办法:将内核版本从5.x换成6.x就没有这个问题了

 

DWIN屏(迪文屏)入门:

屏:DMG100600Y070两块。

第一个要注意的是:这个串口屏有个RS232与TTL的开关,在排线前方芯片组的前方。短接为TTL,不短接为RS232串口模式。

测试串口通讯情况:TTL那块屏串口通讯有问题。要么无回显,要么接收与发送一致,最终未定位出原因。最后重新购买了基于RS232的串口模块后,成功。

串口模块:在win11安装驱动,在硬件驱动处,将波特率改为115200;

然后用sscom串口软件,发送AA 00 CC 33 C3 3C握手信号,设备返回AA 00 4F 4B 5F 56 31 2E 36 00 00 00 00 00 CC 33 C3 3C,应该说明是成功了。

附常用指令:

 修改注释:双击那些十六进制框,就可以更改注释。

 framebuffer总是存在光标的解决办法:

在/etc/profile里,加入:tput civis,就不会在framebuffer上出现光标及黑块了

要重新打开光标,tput cnorm

负作用:连同其它终端一同禁止了。暂时没有好的办法!

关于hdmi闪烁的问题:

如果连接串口至笔记本,一切正常。但当拔掉串口,HDMI屏总是闪烁,且不能进入ubuntu系统。

解决办法:将板子的串口线与usb转串口的小板子的连接线拆掉,就正常了

 

如何开机自动执行脚本的问题(关键词:rc.local rc-local)

================================================

要想开机后,自动执行某个脚本,经常在centos下用的rc.local。但是ubuntu系统“暂停”了这个功能。下面是恢复方法

在/lib/systemd/system下面,有一个rc-local.service文件,打开这个文件并在末尾增加如下:

[Install]
WantedBy=multi-user.target
Alias=rc-local.service

接下来就是创建/etc/rc.local,该文件的第一行必须是#!/bin/bash,最后一行exit 0,且chmod +x rc.local

然后将需要执行的脚本或程序放到rc.local里。

一切完成后,systemctl reload-daemon ;  systemctl start  rc-local.service

如果rc.local格式不对(如第一行不是shebong),则服务启动会失败

实践反馈:orangepi好象不需要改任何东西,只要将脚本插入/etc/rc.local即可。ubuntu按照以上做法是可以的。

 

增加新的分区:

===================================================================

查看新增加的分区的UUID: 

dumpe2fs -h /dev/mmclk0p2:查看第二分区情况,里面会显示出uuid。如果用dev设备号,有时会出现设备号变化的问题。

UUID=5aecfb3c-5169-4c34-ba4d-9643daa69085      /data  ext4 defaults,noatime,commit=0   0   0

 静态编译问题:

===========================================================

在makefile文件的lib变量里,增加-static,则可进行静态编译。但可能会报很多关于libsqlite3的错误,这实际是由于math库造成。需要把 -lm参数做为最后一个库文件,即可解决。在实际应用中,依然会有两个warning,但不影响使用。

 

DS3231 RTC模块:

调试这个模块前,选关闭chrony服务,避免造成影响。

要在orangepi下使用,可以按照如下方法:

首先看看i2cdetect -y 3,是否能看到68的DS3231模块。

如果能看到,那么执行下面的语句:

echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-3/new_device
再执行i2cdetect,此时发现标识变成了UU(代表Linux驱动接管了)。
此时,再ls /dev/rtc*,会发现多了一个rtc1,这个就是ds3231。我们会发现/dev/rtc链接到了rtc0,那是一个orangepi自带的、无法掉电保存的一个rtc。

我们执行timedatectl,会发现rtc时间是指的/dev/rtc的时间。
我们手工设置一个时间:date -s "2024-3-3"
要想将当前时间保存到ds3231,用hwclock -w -f /dev/rtc1即可。 -w代表将系统时间写入rtc,-f指明rtc设备。如果不加-f,那么就写到默认的/dev/rtc里面了,也就是rtc0里了。
此时分别查看rtc0和rtc1:
hwclock -f /dev/rtc0
hwclock -f /dev/rtc1
我们会发现,这两个的时间是不一致的。

先用timedatectl看一下RTC时间
如果要想用ds3231的rtc1做为默认的rtc,只要简单的将/dev/rtc链接到rtc1即可。ln -f -s /dev/rtc1 /dev/rtc
再用timedatectl看一下RTC时间,应该发现与之前是不一样的。

要想设备启动时,自动读取ds3231的时间,可以将以上命令放置到/etc/rc.local里,示例 如下:
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-3/new_device
sleep 3  #必须进行延迟,否则下面的命令可能不能正常执行
hwclock -s -f /dev/rtc1 #将rtc时间读入成系统时间
实际工作中,是将这些语句写成/etc/init.d/rtc_ds1307脚本里,然后ln到/etc/rc3.d/S01rtc_ds1307里来启动。

#可选:将ds3231做为各种时间命令的默认rtc
ln -f -s /dev/rtc1 /dev/rtc

踩坑:chat-gpt曾建议修改设备树的方法,最终没能成功。不过,这应该是一个最终极的、完美的解决办法,留待以后处理吧。2024.12.14

EMQX windows安装:
=============================
今天(25.8.19)emqx的公用服务出现了问题,自己搭一套还是必要的。在官网下载5.3.2版本里的windows版(高版本已经没有WIN版了),解压。
https://www.emqx.com/zh/downloads/broker/v5.3.2
bin/emqx.cmd install安装
bin/emqx.cmd console 启动服务
此时MQTT服务就可以用了。无用户认证,直接使用
要增加用户认证:
http://127.0.0.1:18083 admin/public
访问控制--客户端认证,增加一个基于username的认证项即可。

EMQX WEB CLIENT:网页版mqtt client
================================
https://mqttx.app/web-client



利用陶晶驰的设计工具(UART HMI软件,与orangepi直接通讯):
===================================================
将orangepi的串口5与windows的com3相连接。
然后打开HMI软件,并导入设计好的HMI文件,选择调试。界面出现后,选左下角的“用户MCU输入”,并设置相应的COM口及波特率(我的环境是com3+115200),此时在orangepi上运行iot,就能在windows上显示出数据
可以点右侧窗口顶部:H S ,点S,能看到ASCII码,比较直观。

DHT11读取程序:
===============================================================
这是根据网友的程序改的,来自树莓派实验论坛,修改解决了第一次启动总是读取不成功的问题。这个程序的效果不错,读取成功率明显高于之前下载的一个程序。但我改动后成功率却有所下降。
编程要点:尽量精简代码,否则过多的代码会造成时间损耗(一个printf就占用了14us左右),造成时序延迟。
在程序开始时习惯性的将GPIO设置为OUPUT,并拉高电平,结果造成不稳定,去掉反而好了。
MCU在拉电平后,通过delay保持一段时间,但是当进入INPUT后,尽量不依靠时间,而是对高低电平的时序判断进行,否则会造成程序的读取成功率不高。
for i循环中的高电平loop,按照理论应放到代码块的后面,但这样却大概率的造成死循环。原因不得而知。
本程序存在死循环风险,引用时建议通过线程引用,超时不退出时就强行杀掉线程。
基于时序的编程是极痛苦的!!!一定一定要详细的阅读文档,精确掌握通讯时序图。尽量避免这种编程方式。从编程难度,程序稳定性方面来看,远远不如i2c方式。到此为止吧,不折腾了!
#include <stdio.h>
#include <stdint.h>
#include <wiringPi.h>

#define TIMEOUT     1000
#define PIN  5

int data[5] = { 0, 0, 0, 0, 0 };
int st = 0;   //是否超时:1==超时

int dht11_read(void) {
    int i;

    pinMode(PIN, OUTPUT);
    //主机发送起始信号(低18;高40)
    digitalWrite(PIN, LOW);
    delay(18+2);
    digitalWrite(PIN, HIGH);
    pinMode(PIN, INPUT);
    pullUpDnControl(PIN, PUD_UP);
    delayMicroseconds(27);

    while ( digitalRead(PIN) == LOW )
        ;
    while ( digitalRead(PIN) == HIGH )
        ;
    //已经进低电平,开始读取数据

    int reg_no = 0;
    for (int reg_no =0; reg_no < 5; reg_no++) {
        data[reg_no] = 0;
        for (i = 0; i < 8; i++) {
           while ( digitalRead(PIN) == HIGH )
                 ;
           while ( digitalRead(PIN) == LOW )
                 ;
                //转入高电平,在28+2时间处,读
            data[reg_no] *= 2;
            delayMicroseconds(32);
            if (digitalRead(PIN) == HIGH)
                data[reg_no]++;
         }
    }
    //恢复(设为output,并拉高电平
    pinMode(PIN, OUTPUT);
    digitalWrite(PIN, HIGH);

    return 0;
}


int main(void) {
    int i;

    if (i = wiringPiSetup() ) {
        printf("WiringPi init error\n");
        return 0;
    }
while (1) {
    dht11_read();
    {
                                printf("H:%d.%d,T:%d.%d\n",data[0],data[1],data[2],data[3]);
    }
    if ( (data[0] + data[1] + data[2] + data[3] )!= data[4] )
        printf("CRC ERROR!!!\n");
    delay(3000);
}
    return 0;
}

 

/*网友原程序,修改解决了第一次启动不能成功读取的问题*/
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>

typedef unsigned char uint8;
typedef unsigned int  uint16;
typedef unsigned long uint32;

#define HIGH_TIME 32

int pinNumber = 5;
uint32 databuf;

uint8 readSensorData(void)
{
    uint8 crc;
    uint8 i;

    pinMode(pinNumber, OUTPUT); // set mode to output
    digitalWrite(pinNumber, LOW); // output a high level
    delay(20);
    digitalWrite(pinNumber, HIGH); // output a low level
    pinMode(pinNumber, INPUT); // set mode to input
    pullUpDnControl(pinNumber, PUD_UP);
    delayMicroseconds(27);

    if (digitalRead(pinNumber) == 0) //SENSOR ANS
    {
        while (digitalRead(pinNumber) == LOW)
            ; //wait to high

        for (i = 0; i < 32; i++)
        {
            while (digitalRead(pinNumber))
                ; //data clock start
            while (!digitalRead(pinNumber))
                ; //data start
            delayMicroseconds(HIGH_TIME);
            databuf *= 2;
            if (digitalRead(pinNumber) == 1) //1
            {
                databuf++;
            }
        }

        for (i = 0; i < 8; i++)
        {
            while (digitalRead(pinNumber))
                ; //data clock start
            while (!digitalRead(pinNumber))
                ; //data start
            delayMicroseconds(HIGH_TIME);
            crc *= 2;
            if (digitalRead(pinNumber) == 1) //1
            {
                crc++;
            }
        }
        return 1;
    }
    else
    {
        return 0;
    }
}

int main(void)
{
    printf("PIN:%d\n", pinNumber);

    if (-1 == wiringPiSetup()) {
        printf("Setup wiringPi failed!");
        return 1;
    }

    printf("Starting...\n");
    while (1)
    {


        if (readSensorData())
        {
            printf("Sensor data read ok!\n");
            printf("RH:%d.%d\n",(int) ((databuf >> 24) & 0xff), (int) ((databuf >> 16) & 0xff));
            printf("TMP:%d.%d\n",(int) (databuf >> 8) & 0xff, (int)databuf & 0xff);
            databuf = 0;
        }
        else
        {
            printf("Sensor dosent ans!!!!!!!!!!!!!!!\n");
            databuf = 0;
        }
        delay(3000);
    }
    return 0;
}

 








posted on 2024-02-25 09:58  胡彼德  阅读(326)  评论(0)    收藏  举报