浪派-造物志

何谓:浪派?

所谓浪派,其实是我和几个朋友一起搞的一个树莓派小车的项目,其核心内容是想在疫情期间无法面基就只好通过网络交互来实现原先的自由自造的折腾行为.其中涉及到原型设计,芯片选型,PCB设计,打样焊接,程序调试等一系列技术栈,在设计之初为了能够让大家都有参与进来的兴趣,还专门采用了kicad设计软件来进行pcb设计...参与的小伙伴各显神通,但是也遭遇过一些小小的滑铁卢...

回忆杀


未完待续,手机更新大拇指压力太大了....

Linux内核编译如果出问题了怎么办?

如果出问题了

如果您遇到的问题似乎是由于内核错误引起的,请检查文件维护者以查看是否有特定人员与您遇到麻烦的内核部分相关联。如果没有列出有任何人,那么第二个最好的办法是将它们邮寄给(torvalds@linux-foundation.org),以及可能的其他任何有关的邮件列表或新闻组。

在所有错误报告中,请告诉您您在操作的是什么内核,如何复制问题以及您的设置是什么(使用常识)。如果问题是新问题,请告诉他,如果问题是旧问题,请在首次发现问题时告诉他,他才是Linux内核最大的BOSS。

例如:
如果该错误导致显示如下消息:

unable to handle kernel paging request at address C0000010
Oops: 0002
EIP:   0010:XXXXXXXX
eax: xxxxxxxx   ebx: xxxxxxxx   ecx: xxxxxxxx   edx: xxxxxxxx
esi: xxxxxxxx   edi: xxxxxxxx   ebp: xxxxxxxx
ds: xxxx  es: xxxx  fs: xxxx  gs: xxxx
Pid: xx, process nr: xx
xx xx xx xx xx xx xx xx xx xx

或屏幕上或系统日志中的类似内核调试信息,请准确复制。转储对您来说似乎令人难以理解,但是它确实包含有助于调试问题的信息。转储上方的文本也很重要:它说明了为什么内核转储代码的原因(在上面的示例中,这是由于内核指针错误引起的)。有关寻找转储的更多信息,请参见“错误查找”

如果使用CONFIG_KALLSYMS编译内核,则可以按原样发送转储,否则,您将不得不使用该ksymoops程序来理解转储(但通常首选使用CONFIG_KALLSYMS进行编译)。可以从https://www.kernel.org/pub/linux/utils/kernel/ksymoops/下载该实用程序 。另外,您可以手动进行转储查找:

在上面的调试转储中,如果您可以查找EIP值的含义,那么它将大有帮助。这样的十六进制值对我或其他人没有太大帮助:它将取决于您的特定内核设置。您应该做的是从EIP行中获取十六进制值(忽略0010:),然后在内核名称列表中查找该值,以查看哪个内核函数包含有问题的地址。

要找出内核函数名称,您需要找到与表现出该症状的内核相关的系统二进制文件。这是文件“ linux/vmlinux”。要提取名称列表并将其与内核崩溃时的EIP匹配,请执行以下操作:

nm vmlinux | sort | less

这将为您提供按升序排序的内核地址列表,从中可以轻松找到包含违规地址的函数。请注意,内核调试消息给出的地址不一定与功能地址完全匹配(实际上,这不太可能),因此您不能只是“ grep”列表:但是,列表将为您提供每个内核函数的起始点,因此,通过查找起始地址比您要查找的起始地址低的函数,然后查找具有较高地址的函数,可以找到所需的起始地址。实际上,在问题报告中包括一些“上下文”可能是个好主意,在有趣的地方加上几行即可。

如果由于某种原因您不能执行上述操作(您有预编译的内核映像或类似文件),请尽可能多地告诉他有关您的设置的信息。有关详细信息,请阅读“报告问题”。

另外,您可以在运行的内核上使用gdb。(只读;即,您不能更改值或设置断点。)为此,首先使用-g编译内核;适当地编辑arch/x86/Makefile,然后执行。您还需要启用CONFIG_PROC_FS(通过)。

make cleanmake config

使用新内核重新引导后,请执行。现在,您可以使用所有常用的gdb命令。查找系统崩溃点的命令是。(用EIP值替换XXXes。)

gdb vmlinux /proc/kcorel *0xXXXXXXXX

当前,对非运行内核进行gdb操作失败,因为gdb(错误地)无视了为其编译内核的起始偏移量。

Linux内核编译前需要了解的内容

 Linux内核版本5.x

  • < http://kernel.org/ >
    这些是Linux版本5的发行说明。请仔细阅读它们,因为它们告诉您所有内容,解释如何安装内核以及出现问题时应采取的措施。

什么是Linux?

Linux是Unix操作系统的克隆,由Linus Torvalds在网络松散的黑客团队的协助下从零开始编写。它旨在实现POSIX和Single UNIX规范的合规性。

它具有您在现代的成熟Unix中所期望的所有功能,包括真正的多任务,虚拟内存,共享库,需求加载,共享的写时复制可执行文件,适当的内存管理以及包括IPv4和IPv6在内的多堆栈网络。

它根据GNU通用公共许可证v2分发-有关更多详细信息,请参见随附的COPYING文件。

 它在什么硬件上运行?

尽管最初最初是为基于32位x86的PC(386或更高版本)开发的,但今天的Linux也可以(至少)在Compaq Alpha AXP,Sun SPARC和UltraSPARC,Motorola 68000,PowerPC,PowerPC64,ARM,Hitachi SuperH,Cell上运行,IBM S / 390,MIPS,HP PA-RISC,英特尔IA-64,DEC VAX,AMD x86-64 Xtensa和ARC体系结构。

只要具有分页内存管理单元(PMMU)和GNU C编译器(gcc)的端口(属于GNU编译器集合,GCC的一部分),Linux便可以轻松移植到大多数通用的32位或64位体系结构中。 。尽管功能显然受到限制,但Linux也已移植到许多没有PMMU的体系结构中。Linux也已移植到其自身。现在,您可以将内核作为用户空间应用程序运行-这称为UserMode Linux(UML)。

文献资料

互联网上和书籍中都有许多电子形式的文档,既特定于Linux,又涉及一般的UNIX问题。我建议您查看任何Linux FTP站点上的LDP(Linux文档项目)书籍的文档子目录。本README并不是系统上的文档:有更好的可用资源。
Documentation /子目录中有各种README文件:例如,这些文件通常包含某些驱动程序的特定于内核的安装说明。

安装内核源文件

如果安装完整源代码,请将内核tarball放在您具有权限的目录中(例如,主目录)并解压缩它:

xz -cd linux-5.x.tar.xz | tar xvf -

将“ X”替换为最新内核的版本号。

不要使用/usr/src/linux 路径!该区域具有(通常不完整)一组由库的头文件使用的内核头文件。它们应该与库匹配,并且不会因kernel-du-jour碰巧而陷入混乱。

您也可以通过补丁在5.x版本之间升级内核。补丁以xz格式分发。要通过补丁安装,请获取所有较新的补丁文件,输入内核源代码的顶层目录(linux-5.x)并执行:

xz -cd ../patch-5.x.xz | patch -p1

对于大于当前源代码树in_order版本“ x”的所有版本替换“ x” ,您应该可以。您可能要删除备份文件(some-file-name〜或some-file-name.orig),并确保没有失败的补丁程序(some-file-name#或some-file-name.rej)。 。如果有,则您或我都犯了一个错误。

与5.x内核的修补程序不同,5.xy内核(也称为-stable内核)的修补程序不是增量的,而是直接应用于基本5.x内核。例如,如果您的基本内核是5.0,并且您想应用5.0.3补丁程序,则一定不要首先应用5.0.1和5.0.2补丁程序。同样,如果您正在运行5.0.2内核版本并希望跳至5.0.3,则必须先反转5.0.2补丁(即补丁-R),然后再应用5.0.3补丁。

另外,脚本patch-kernel可用于自动执行此过程。它确定当前的内核版本并应用找到的所有修补程序:

linux/scripts/patch-kernel linux

上面命令中的第一个参数是内核源的位置。打补丁的程序是从当前目录的应用程序,但是可以将备用目录指定为第二个参数。

  • 确保您周围没有旧的.o文件和依赖项:
    cd linux
    make mrproper

    您现在应该正确安装了内核源码。

 软件需求

编译和运行5.x内核需要各种软件包的最新版本。请教 编译内核所需的最低版本号的最低要求以及如何获取这些软件包的更新。请注意,使用这些软件包的旧版本可能会导致间接错误,很难跟踪,因此请不要假定您仅在构建或操作过程中出现明显问题时才可以更新软件包。

 内核的构建目录

默认情况下,编译内核时,所有输出文件将与内核源代码一起存储。使用该选项,您可以为输出文件(包括.config)指定备用位置。例:

make O=output/dir
kernel source code: /usr/src/linux-5.x
build directory:    /home/name/build/kernel

要配置和构建内核,请使用:

cd /usr/src/linux-5.x
make O=/home/name/build/kernel menuconfig
make O=/home/name/build/kernel
sudo make O=/home/name/build/kernel modules_install install
  • 请注意:如果使用该O=output/dir选项,则必须将其用于所有的make调用。

配置内核

即使仅升级一个次要版本,也不要跳过此步骤。每个版本中都添加了新的配置选项,如果未按预期设置配置文件,则会出现奇怪的问题。如果要以最少的工作量将现有配置带到新版本,请使用,它只会询问您新问题的答案。

make oldconfig

备用配置命令是:

"make config"      Plain text interface.
"make menuconfig"  Text based color menus, radiolists & dialogs.
"make nconfig"     Enhanced text based color menus.
"make xconfig"     Qt based configuration tool.
"make gconfig"     GTK+ based configuration tool.
"make oldconfig"   Default all questions based on the contents of
                   your existing ./.config file and asking about
                   new config symbols.
"make olddefconfig"
                   Like above, but sets new symbols to their default
                   values without prompting.
"make defconfig"   Create a ./.config file by using the default
                   symbol values from either arch/$ARCH/defconfig
                   or arch/$ARCH/configs/${PLATFORM}_defconfig,
                   depending on the architecture.
"make ${PLATFORM}_defconfig"
                   Create a ./.config file by using the default
                   symbol values from
                   arch/$ARCH/configs/${PLATFORM}_defconfig.
                   Use "make help" to get a list of all available
                   platforms of your architecture.
"make allyesconfig"
                   Create a ./.config file by setting symbol
                   values to 'y' as much as possible.
"make allmodconfig"
                   Create a ./.config file by setting symbol
                   values to 'm' as much as possible.
"make allnoconfig" Create a ./.config file by setting symbol
                   values to 'n' as much as possible.
"make randconfig"  Create a ./.config file by setting symbol
                   values to random values.
"make localmodconfig" Create a config based on current config and
                      loaded modules (lsmod). Disables any module
                      option that is not needed for the loaded modules.

                      To create a localmodconfig for another machine,
                      store the lsmod of that machine into a file
                      and pass it in as a LSMOD parameter.

                      Also, you can preserve modules in certain folders
                      or kconfig files by specifying their paths in
                      parameter LMC_KEEP.

              target$ lsmod > /tmp/mylsmod
              target$ scp /tmp/mylsmod host:/tmp

              host$ make LSMOD=/tmp/mylsmod \
                      LMC_KEEP="drivers/usb:drivers/gpu:fs" \
                      localmodconfig

                      The above also works when cross compiling.

"make localyesconfig" Similar to localmodconfig, except it will convert
                      all module options to built in (=y) options. You can
                      also preserve modules by LMC_KEEP.
"make kvmconfig"   Enable additional options for kvm guest kernel support.
"make xenconfig"   Enable additional options for xen dom0 guest kernel
                   support.
"make tinyconfig"  Configure the tiniest possible kernel.

您可以在Kconfig make config中找到有关使用Linux内核配置工具的更多信息。

关于的注释:make config

拥有不必要的驱动程序会使内核变大,并且在某些情况下可能会导致问题:检测不存在的控制器可能会使您的其他控制器卡住。
如果存在带有编译的数学仿真的内核,则仍将使用协处理器:在这种情况下,永远不会使用数学仿真。内核会稍大一些,但是无论它们是否具有数学协处理器,它都可以在不同的机器上工作。
“内核hacking”配置细节通常会导致更大或更慢的内核(或同时出现这两者),并且甚至可以通过配置一些例程来主动尝试破坏坏代码以发现内核问题(kmalloc()),从而降低内核的稳定性。因此,您可能应该对“开发”,“实验”或“调试”功能的问题回答“ n”。

 编译内核

确保您至少有可用的gcc 4.9。有关更多信息,请参阅编译内核的最低要求。

请注意,您仍然可以使用此内核运行a.out用户程序。

执行make以创建压缩的内核映像。如果您已经安装了适合内核makefile的lilo,也可以这样做,但是您可能需要首先检查特定的lilo设置。

make install

要进行实际安装,您必须是root用户,但是任何正常的构建都不需要这样做。

如果将内核的任何部分都配置为modules,则还必须这样做。

make modules_install

详细的内核编译/生成输出:

通常,内核构建系统以相当安静的模式运行(但不是完全安静)。
但是,有时您或其他内核开发人员需要在执行时完全看到编译,链接或其他命令。
为此,请使用“详细”构建模式。这可以通过传递V=1给make命令来完成 ,例如:

make V=1 all

要使构建系统还告诉您重建每个目标的原因,请使用V=2。默认值为V=0

  • 万一出现问题,请随时准备备份内核。
    对于开发版本尤其如此,因为每个新版本都包含尚未调试的新代码。
    确保还保留了与该内核对应的模块的备份。
    如果要安装与工作内核具有相同版本号的新内核,请在执行之前对modules目录进行备份。

    make modules_install

    另外,在编译之前,请使用内核配置选项LOCALVERSION将唯一的后缀附加到常规内核版本中。可以在常规设置菜单中设置LOCALVERSION

为了引导您的新内核,您需要将内核映像(例如,编译后的…/linux/arch/x86/boot/bzImage)复制到找到常规可引导内核的位置。

** 不再支持在没有引导加载程序(例如LILO)帮助的情况下直接从软盘引导内核。

如果从硬盘驱动器引导Linux,则有可能使用LILO,LILO使用文件/etc/lilo.conf中指定的内核映像。内核映像文件通常是/vmlinuz,/boot/vmlinuz,/ bzImage或/boot bzImage。
要使用新内核,请保存旧内核的副本,然后将新内核镜像复制到旧内核镜像上。然后,您必须重新运行LILO才能更新加载映射!否则,您将无法引导新的内核镜像。

  • 重新安装LILO通常是运行/sbin/lilo的问题。您可能希望编辑/etc/lilo.conf为旧内核映像(例如/vmlinux.old)指定一个条目,以防新内核映像不起作用。有关更多信息,请参见LILO文档。

  • 重新安装LILO之后,您应该已经准备就绪。

  • 关闭系统,重新启动,然后享受!

如果您需要在内核映像中更改默认的根设备,视频模式等,请在适当的地方使用引导加载程序的引导选项。无需重新编译内核即可更改这些参数。

  • 使用新内核重新启动并开始浪吧!

Linux内核编译环境详解

Minimal requirements to compile the Kernel

Intro

This document is designed to provide a list of the minimum levels of software necessary to run the 4.x kernels.

This document is originally based on my “Changes” file for 2.0.x kernels and therefore owes credit to the same people as that file (Jared Mauch, Axel Boldt, Alessandro Sigala, and countless other users all over the ‘net).

Current Minimal Requirements

Upgrade to at least these software revisions before thinking you’ve encountered a bug! If you’re unsure what version you’re currently running, the suggested command should tell you.

Again, keep in mind that this list assumes you are already functionally running a Linux kernel. Also, not all tools are necessary on all systems; obviously, if you don’t have any PC Card hardware, for example, you probably needn’t concern yourself with pcmciautils.

Program Minimal version Command to check the version
GNU C 4.9 gcc –version
Clang/LLVM (optional) 10.0.1 clang –version
GNU make 3.81 make –version
binutils 2.23 ld -v
flex 2.5.35 flex –version
bison 2.0 bison –version
util-linux 2.10o fdformat –version
kmod 13 depmod -V
e2fsprogs 1.41.4 e2fsck -V
jfsutils 1.1.3 fsck.jfs -V
reiserfsprogs 3.6.3 reiserfsck -V
xfsprogs 2.6.0 xfs_db -V
squashfs-tools 4.0 mksquashfs -version
btrfs-progs 0.18 btrfsck
pcmciautils 004 pccardctl -V
quota-tools 3.09 quota -V
PPP 2.4.0 pppd –version
nfs-utils 1.0.5 showmount –version
procps 3.2.0 ps –version
oprofile 0.9 oprofiled –version
udev 081 udevd –version
grub 0.93 grub –version / grub-install –version
mcelog 0.6 mcelog –version
iptables 1.4.2 iptables -V
openssl & libcrypto 1.0.0 openssl version
bc 1.06.95 bc –version
Sphinx[1] 1.3 sphinx-build –version
  • [1] Sphinx is needed only to build the Kernel documentation

    Kernel compilation

  • GCC
    The gcc version requirements may vary depending on the type of CPU in your computer.

  • Clang/LLVM (optional)
    The latest formal release of clang and LLVM utils (according to releases.llvm.org) are supported for building kernels. Older releases aren’t guaranteed to work, and we may drop workarounds from the kernel that were used to support older versions. Please see additional docs on Building Linux with Clang/LLVM.

  • Make
    You will need GNU make 3.81 or later to build the kernel.

  • Binutils
    Binutils 2.23 or newer is needed to build the kernel.

  • pkg-config
    The build system, as of 4.18, requires pkg-config to check for installed kconfig tools and to determine flags settings for use in ‘make {g,x}config’. Previously pkg-config was being used but not verified or documented.

  • Flex
    Since Linux 4.16, the build system generates lexical analyzers during build. This requires flex 2.5.35 or later.

  • Bison
    Since Linux 4.16, the build system generates parsers during build. This requires bison 2.0 or later.

  • Perl
    You will need perl 5 and the following modules: Getopt::Long, Getopt::Std, File::Basename, and File::Find to build the kernel.

  • BC
    You will need bc to build kernels 3.10 and higher

  • OpenSSL
    Module signing and external certificate handling use the OpenSSL program and crypto library to do key creation and signature generation.

You will need openssl to build kernels 3.7 and higher if module signing is enabled. You will also need openssl development packages to build kernels 4.3 and higher.

System utilities

32-bit UID support is now in place. Have fun!

Linux documentation for functions is transitioning to inline documentation via specially-formatted comments near their definitions in the source. These comments can be combined with ReST files the Documentation/ directory to make enriched documentation, which can then be converted to PostScript, HTML, LaTex, ePUB and PDF files. In order to convert from ReST format to a format of your choice, you’ll need Sphinx.

  • Util-linux
    New versions of util-linux provide fdisk support for larger disks, support new options to mount, recognize more supported partition types, have a fdformat which works with 2.4 kernels, and similar goodies. You’ll probably want to upgrade.

  • Ksymoops
    If the unthinkable happens and your kernel oopses, you may need the ksymoops tool to decode it, but in most cases you don’t. It is generally preferred to build the kernel with CONFIG_KALLSYMS so that it produces readable dumps that can be used as-is (this also produces better output than ksymoops). If for some reason your kernel is not build with CONFIG_KALLSYMS and you have no way to rebuild and reproduce the Oops with that option, then you can still decode that Oops with ksymoops.

  • Mkinitrd
    These changes to the /lib/modules file tree layout also require that mkinitrd be upgraded.

  • E2fsprogs
    The latest version of e2fsprogs fixes several bugs in fsck and debugfs. Obviously, it’s a good idea to upgrade.

  • JFSutils
    The jfsutils package contains the utilities for the file system. The following utilities are available:

  • fsck.jfs - initiate replay of the transaction log, and check and repair a JFS formatted partition.

  • mkfs.jfs - create a JFS formatted partition.
    other file system utilities are also available in this package.

  • Reiserfsprogs
    The reiserfsprogs package should be used for reiserfs-3.6.x (Linux kernels 2.4.x). It is a combined package and contains working versions of mkreiserfs, resize_reiserfs, debugreiserfs and reiserfsck. These utils work on both i386 and alpha platforms.

  • Xfsprogs
    The latest version of xfsprogs contains mkfs.xfs, xfs_db, and the xfs_repair utilities, among others, for the XFS filesystem. It is architecture independent and any version from 2.0.0 onward should work correctly with this version of the XFS kernel code (2.6.0 or later is recommended, due to some significant improvements).

  • PCMCIAutils
    PCMCIAutils replaces pcmcia-cs. It properly sets up PCMCIA sockets at system startup and loads the appropriate modules for 16-bit PCMCIA devices if the kernel is modularized and the hotplug subsystem is used.

  • Quota-tools
    Support for 32 bit uid’s and gid’s is required if you want to use the newer version 2 quota format. Quota-tools version 3.07 and newer has this support. Use the recommended version or newer from the table above.

  • Intel IA32 microcode
    A driver has been added to allow updating of Intel IA32 microcode, accessible as a normal (misc) character device. If you are not using udev you may need to:

mkdir /dev/cpu
mknod /dev/cpu/microcode c 10 184
chmod 0644 /dev/cpu/microcode
as root before you can use this. You’ll probably also want to get the user-space microcode_ctl utility to use with this.

  • udev
    udev is a userspace application for populating /dev dynamically with only entries for devices actually present. udev replaces the basic functionality of devfs, while allowing persistent device naming for devices.

  • FUSE
    Needs libfuse 2.4.0 or later. Absolute minimum is 2.3.0 but mount options direct_io and kernel_cache won’t work.

Networking

  • General changes
    If you have advanced network configuration needs, you should probably consider using the network tools from ip-route2.

  • Packet Filter / NAT
    The packet filtering and NAT code uses the same tools like the previous 2.4.x kernel series (iptables). It still includes backwards-compatibility modules for 2.2.x-style ipchains and 2.0.x-style ipfwadm.

  • PPP
    The PPP driver has been restructured to support multilink and to enable it to operate over diverse media layers. If you use PPP, upgrade pppd to at least 2.4.0.

If you are not using udev, you must have the device file /dev/ppp which can be made by:

mknod /dev/ppp c 108 0
as root.

  • NFS-utils
    In ancient (2.4 and earlier) kernels, the nfs server needed to know about any client that expected to be able to access files via NFS. This information would be given to the kernel by mountd when the client mounted the filesystem, or by exportfs at system startup. exportfs would take information about active clients from /var/lib/nfs/rmtab.

This approach is quite fragile as it depends on rmtab being correct which is not always easy, particularly when trying to implement fail-over. Even when the system is working well, rmtab suffers from getting lots of old entries that never get removed.

With modern kernels we have the option of having the kernel tell mountd when it gets a request from an unknown host, and mountd can give appropriate export information to the kernel. This removes the dependency on rmtab and means that the kernel only needs to know about currently active clients.

To enable this new functionality, you need to:

mount -t nfsd nfsd /proc/fs/nfsd
before running exportfs or mountd. It is recommended that all NFS services be protected from the internet-at-large by a firewall where that is possible.

  • mcelog
    On x86 kernels the mcelog utility is needed to process and log machine check events when CONFIG_X86_MCE is enabled. Machine check events are errors reported by the CPU. Processing them is strongly encouraged.

Kernel documentation

  • Sphinx
    Please see Sphinx Install in Introduction for details about Sphinx requirements.

Getting updated software

Retropie 设置中文

RetroPie复古游戏模拟系统设置中文

步骤简述

    1. 下载最新的Retropie镜像,别问我从哪里下载。
    1. 烧录到TF卡,也别问我怎么烧录。
    1. 开机启动后连wifi或者网络, 更别问我怎么连wifi。
    1. 进系统后直接按F4进入终端,在确保联网的情况下输入:
      sudo apt-get update 
      sudo apt-get -y install fonts-droid-fallback
      sudo reboot 

      然后你安装的游戏就算是有中文也没有问题了。

Linux 系统中用C语言调用串口

总览

不幸的是,在Linux中使用串行端口并不是世界上最简单的事情。在处理termios.h标头时,存在许多复杂的设置,这些设置隐藏在价值多个字节的位域中。该页面试图帮助解释这些设置,并向您展示如何在Linux中正确配置串行端口。

一切都是文件

在典型的UNIX风格中,串行端口由操作系统中的文件表示。这些文件通常会弹出/dev/,并以name开头tty*。

常用名称是:

  • /dev/ttyACM0-ACM代表USB总线上的ACM调制解调器。Arduino UNO(及类似名称)将使用此名称显示。
  • /dev/ttyPS0 -运行基于Yocto的Linux构建的Xilinx Zynq FPGA将使用此名称作为Getty连接到的默认串行端口。
  • /dev/ttyS0-标准COM端口将具有此名称。如今,由于较新的台式机和笔记本电脑没有实际的COM端口,这些情况已经不太普遍了。
  • /dev/ttyUSB0 -大多数USB到串行电缆将使用这样的文件显示。
  • /dev/pts/0-伪终端。这些可以通过生成socat。
    Linux和连接的Arduino的/dev/目录的列表。 Arduino串行端口显示为/dev/ttyACMO0。
    Linux和连接的Arduino的/dev/目录的列表。Arduino串行端口显示为/dev/ttyACMO0。

要写入串行端口,请写入文件。要从串行端口读取,请从文件读取。当然,这允许您发送/接收数据,但是如何设置串行端口参数,例如波特率,奇偶校验等?这是通过特殊tty配置设置的struct。

C语言的基本设置

  • 注意
    此代码也适用于C ++。
    首先,我们要包括一些内容:
// C library headers
#include <stdio.h>
#include <string.h>

// Linux headers
#include <fcntl.h> // Contains file controls like O_RDWR
#include <errno.h> // Error integer and strerror() function
#include <termios.h> // Contains POSIX terminal control definitions
#include <unistd.h> // write(), read(), close()
然后,我们要打开串行端口设备(在下方显示为文件/dev/),保存由返回的文件描述符open():

int serial_port = open("/dev/ttyUSB0", O_RDWR);

# Check for errors
if (serial_port < 0) {
    printf("Error %i from open: %s\n", errno, strerror(errno));
}

一个你可能会看到这里的常见错误是errno = 2,和strerror(errno)回报No such file or directory。确保您具有正确的设备路径,并且该设备存在!

您可能会在这里遇到的另一个常见错误errno = 13是Permission denied。这通常是因为当前用户不属于拨出组。使用以下命令将当前用户添加到拨出组:

$ sudo adduser $USER dialout

这些组更改生效之前,您必须先注销然后重新登录。
在这一点上,我们可以从技术上对串行端口进行读写,但是由于默认配置设置不是为串行端口设计的,因此它可能无法工作。因此,现在我们将正确设置配置。
修改任何配置值时,最佳做法是仅修改您感兴趣的位,而保留该字段的所有其他位。这就是为什么你会看到使用下面&=或者|=,从来没有&或|设置位时。

配置设置

我们需要访问该termios结构才能配置串行端口。我们将创建一个新termios结构,然后使用写入串行端口的现有配置tcgetattr(),然后根据需要修改参数并使用保存设置tcsetattr()。

// Create new termios struc, we call it 'tty' for convention
// No need for "= {0}" at the end as we'll immediately write the existing
// config to this struct
struct termios tty;

// Read in existing settings, and handle any error
if(tcgetattr(serial_port, &tty) != 0) {
    printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
}

现在,我们可以tty根据需要更改的设置,如以下各节所示。

控制模式(c_cflags)

该结构的c_cflags成员termios包含控制参数字段。

  • PARENB(平价)
    如果该位置1,则启用奇偶校验位的生成和检测。大多数串行通信不使用奇偶校验位,因此,如果不确定,请清除该位。
tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
tty.c_cflag |= PARENB;  // Set parity bit, enabling parity

CSTOPB(数字停止位)
如果该位置1,则使用两个停止位。如果清除该位,则仅使用一个停止位。大多数串行通信仅使用一个停止位。

tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
tty.c_cflag |= CSTOPB;  // Set stop field, two stop bits used in communication

每字节位数

该CS字段中设置多少个数据位,每个字节通过串行端口传输。此处最常见的设置是8(CS8)。如果不确定,请绝对使用此端口,在此之前我从未使用过未使用8的串行端口(但它们确实存在)。

tty.c_cflag |= CS5; // 5 bits per byte
tty.c_cflag |= CS6; // 6 bits per byte
tty.c_cflag |= CS7; // 7 bits per byte
tty.c_cflag |= CS8; // 8 bits per byte (most common)

流量控制(CRTSCTS)

如果CRTSCTS设置了该字段,则启用硬件RTS / CTS流控制。这里最常见的设置是禁用它。当应禁用此功能时启用它可能会导致您的串行端口不接收任何数据,因为发送方将无限期地对其进行缓冲,等待您“就绪”。

tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
tty.c_cflag |= CRTSCTS;  // Enable RTS/CTS hardware flow control

CREAD和CLOCAL

设置CLOCAL将禁用调制解调器特定的信号线,例如载波检测。SIGHUP当检测到调制解调器断开连接时,还可以防止控制过程发送信号,这通常是一件好事。设置CLOCAL使我们能够读取数据(我们绝对想要!)。

tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)

本地模式(c_lflag)

  • 禁用规范模式
    UNIX系统提供输入,的两种基本模式的规范和非规范模式。在规范模式下,当收到换行符时,将处理输入。接收应用程序逐行接收该数据。在处理串行端口时,这通常是不希望的,因此我们通常要禁用规范模式。

通过以下方式禁用了规范模式:

tty.c_lflag &= ~ICANON;

同样,在规范模式下,某些字符(例如退格键)会被特殊对待,并用于编辑当前文本行(擦除)。同样,我们不希望此功能处理原始串行数据,因为它将导致特定字节丢失!

ECHO

如果该位置1,发送的字符将被回显。因为我们禁用了规范模式,所以我认为这些位实际上没有任何作用,但是以防万一,以防万一!

tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo

禁用信号字符

当该ISIG位置1时INTR,QUIT和会SUSP被解释。我们不希望使用串行端口,因此请清除以下位:

tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP

输入模式(c_iflag)

该结构的c_iflag成员termios包含用于输入处理的低级设置。所述c_iflag构件是一个int。

软件流控制(IXOFF,IXON,IXANY)

结算IXOFF,IXON并IXANY禁用软件流控制,这是我们不想要的:

tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl

禁用接收时字节的特殊处理

清除以下所有位将禁用对字节的任何特殊处理,因为这些字节在被串行端口接收并传递给应用程序之前。我们只想要原始数据,谢谢!

tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes

输出模式(c_oflag)

结构的c_oflag成员termios包含用于输出处理的低级设置。配置串行端口时,我们要禁用对输出字符/字节的任何特殊处理,因此请执行以下操作:

tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
// tty.c_oflag &= ~OXTABS; // Prevent conversion of tabs to spaces (NOT PRESENT IN LINUX)
// tty.c_oflag &= ~ONOEOT; // Prevent removal of C-d chars (0x004) in output (NOT PRESENT IN LINUX)

双方OXTABS并ONOEOT没有在Linux的定义。但是Linux确实具有XTABS似乎相关的领域。为Linux编译时,我只排除了这两个字段,并且串行端口仍然可以正常工作。

VMIN和VTIME(c_cc)

VMIN对于试图在Linux中配置串行端口的许多程序员来说,这VTIME是一个混乱的根源。

需要注意的重要一点是,VTIME根据内容的不同,含义也有所不同VMIN。当VMIN为0时,VTIME指定从read()调用开始的超时。但是当VMIN>> 0时,VTIME指定从第一个接收到的字符开始的超时时间。

让我们探索不同的组合:

  • VMIN = 0,VTIME = 0:无阻塞,立即返回可用值
  • VMIN> 0,VTIME = 0:这将read()始终等待字节(确切地由决定多少个字节VMIN),因此read()可以无限期地阻塞。
  • VMIN = 0,VTIME> 0:这是对最大超时(由给出VTIME)的任何数字字符的阻塞读取。read()将阻塞直到有大量数据可用或发生超时为止。这恰好是我最喜欢的模式(也是我最常使用的模式)。
  • VMIN> 0,VTIME> 0:阻塞直到VMIN接收到任何字符或VTIME第一个字符过去。请注意,VTIME直到收到第一个字符,超时才会开始。
  • VMIN和VTIME都定义为type cc_t,我一直看到它是unsigned char(1个字节)的别名。这使VMIN字符数的上限为255,最大超时为25.5秒(255分秒)。

“一旦收到任何数据,立即返回”并不意味着您一次只能得到1个字节。根据操作系统延迟,串行端口速度,硬件缓冲区以及您无法直接控制的许多其他因素,您可能会收到任意数量的字节。

例如,如果我们要等待最多1秒的时间,一旦收到任何数据就返回,我们可以使用:

tty.c_cc[VTIME] = 10;    // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
tty.c_cc[VMIN] = 0;

波特率

而不是使用位字段与所有其他设置,串口波特率是通过调用函数集cfsetispeed()和cfsetospeed(),传递的一个指针tty结构和enum:

// Set in/out baud rate to be 9600
cfsetispeed(&tty, B9600);
cfsetospeed(&tty, B9600);

如果要保持UNIX兼容,则必须从以下一项中选择波特率:

B0,  B50,  B75,  B110,  B134,  B150,  B200, B300, B600, B1200, B1800, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800

如果使用GNU C库进行编译,则可以放弃这些枚举,而直接指定整数波特率,例如:

// Specifying a custom baud rate when using GNU C
cfsetispeed(&tty, 104560);
cfsetospeed(&tty, 104560);

并非所有硬件都支持所有波特率,因此如果可以选择的话,最好坚持使用上述标准BXXX速率之一。如果您不知道波特率是多少,并且尝试与第三方系统通信,请尝试B9600,然后B57600再尝试,B115200因为它们是最常用的速率。

  • 有关Linux串行端口代码示例,请参见https://github.com/gbmhunter/CppLinuxSerial。

保存termios

更改这些设置后,我们可以使用以下命令保存ttytermios结构tcsetattr():

// Save tty settings, also checking for error
if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
    printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
}

读写

现在我们已经打开并配置了串行端口,我们可以对其进行读写了!

  • 写入
    通过该write()功能完成对Linux串行端口的写入。我们使用serial_port从open()上面的调用返回的文件描述符。
unsigned char msg[] = { 'H', 'e', 'l', 'l', 'o', '\r' };
write(serial_port, "Hello, world!", sizeof(msg));

读取

通过该read()功能进行读取。您必须为Linux提供缓冲区以将数据写入其中。

// Allocate memory for read buffer, set size according to your needs
char read_buf [256];

// Read bytes. The behaviour of read() (e.g. does it block?,
// how long does it block for?) depends on the configuration
// settings above, specifically VMIN and VTIME
int n = read(serial_port, &read_buf, sizeof(read_buf));

// n is the number of bytes read. n may be 0 if no bytes were received, and can also be negative to signal an error.

关闭串口

这很简单:

close(serial_port)

完整的例子

// C library headers
#include <stdio.h>
#include <string.h>

// Linux headers
#include <fcntl.h> // Contains file controls like O_RDWR
#include <errno.h> // Error integer and strerror() function
#include <termios.h> // Contains POSIX terminal control definitions
#include <unistd.h> // write(), read(), close()

// Open the serial port. Change device path as needed (currently set to an standard FTDI USB-UART cable type device)
int serial_port = open("/dev/ttyUSB0", O_RDWR);

// Create new termios struc, we call it 'tty' for convention
struct termios tty;

// Read in existing settings, and handle any error
if(tcgetattr(serial_port, &tty) != 0) {
    printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
}

tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
tty.c_cflag |= CS8; // 8 bits per byte (most common)
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)

tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes

tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
// tty.c_oflag &= ~OXTABS; // Prevent conversion of tabs to spaces (NOT PRESENT ON LINUX)
// tty.c_oflag &= ~ONOEOT; // Prevent removal of C-d chars (0x004) in output (NOT PRESENT ON LINUX)

tty.c_cc[VTIME] = 10;    // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
tty.c_cc[VMIN] = 0;

// Set in/out baud rate to be 9600
cfsetispeed(&tty, B9600);
cfsetospeed(&tty, B9600);

// Save tty settings, also checking for error
if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
    printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
}

// Write to serial port
unsigned char msg[] = { 'H', 'e', 'l', 'l', 'o', '\r' };
write(serial_port, "Hello, world!", sizeof(msg));

// Allocate memory for read buffer, set size according to your needs
char read_buf [256];

// Normally you wouldn't do this memset() call, but since we will just receive
// ASCII data for this example, we'll set everything to 0 so we can
// call printf() easily.
memset(&read_buf, '\0', sizeof(read_buf);

// Read bytes. The behaviour of read() (e.g. does it block?,
// how long does it block for?) depends on the configuration
// settings above, specifically VMIN and VTIME
int num_bytes = read(serial_port, &read_buf, sizeof(read_buf));

// n is the number of bytes read. n may be 0 if no bytes were received, and can also be -1 to signal an error.
if (num_bytes < 0) {
    printf("Error reading: %s", strerror(errno));
}

// Here we assume we received ASCII data, but you might be sending raw bytes (in that case, don't try and
// print it to the screen like this!)
printf("Read %i bytes. Received message: %s", num_bytes, read_buf);

close(serial_port)

getty的问题

如果getty试图管理tty要与之进行串行通信的同一设备,它可能会引起串行通信问题。

停止getty:

getty很难停止,因为默认情况下,如果您尝试杀死进程,那么新进程将立即启动。

这些说明适用于旧版本的Linux和/或嵌入式Linux。

加载/etc/inittab您喜欢的文本编辑器。
注释掉涉及getty到您的tty设备的所有行。
保存并关闭文件。
运行命令~$ init q以重新加载/etc/inittab文件。
终止设备上所有正在运行的getty进程tty。他们现在应该死了!

进程独立占用

最好尝试同时防止其他进程对串行端口进行读/写操作。
实现此目的的一种方法是使用flock()系统调用:

#include <sys/file.h>

int main() {

    // ... get file descriptor here

    // Acquire non-blocking exclusive lock
    if(flock(fd, LOCK_EX | LOCK_NB) == -1) {
        throw std::runtime_error("Serial port with file descriptor " + 
            std::to_string(fd) + " is already locked by another process.");
    }

    // ... read/write to serial port here
}

例子

有关Linux串行端口代码示例,请参见https://github.com/gbmhunter/CppLinuxSerial(请注意,该库是用C ++而不是C编写的)。

外部资源

有关结构配置参数的官方规范,请参见http://www.gnu.org/software/libc/manual/html_node/Terminal-Modes.htmltermios。

MySQL 小结

1. 备份数据库中的表。

1.1 选择备份路径,执行备份。

退出mysql客户端并切换到D盘,d:

mysqldump -u root -p employee > myemployee.sql

注: employee 是数据库名, myemployee.sql 是备份文件名
确认成功后,尝试删除数据库

2. 删除数据库

mysql -u root -p 
mysql> drop database 数据库名;
mysql> drop database employee;

3. 尝试恢复数据库。

3.1 先创建数据库

mysql -u root -p 
passwd: xxxxxx
mysql> create database employee;
mysql> exit
d:\> mysql -u root -p employee < myemployee.sql   还原数据库中的表
password: xxxxxx
d:\> mysql -u root -p 
password: xxxxxx
mysql> show databases;     显示数据库
mysql> use employee;     打开数据库
mysql> desc employee_tbl;   描述表结构
mysql> show tables;  显示表名

3.2 一条命令执行查询的方法:

D:\>mysql -u root -pzypxxx -e "use employee; select coalesce(name,'总数:'), SUM(signin) as sigin_total from employee_tbl group by name with rollup;"

4. 额外创建一个表user_into

mysql> use employee;
mysql> create table user_info (
-> `id`  int(11) NOT NULL, 
-> `name` varchar(10) NOT NULL DEFAULT '',
-> `age`  int(3) NOT NULL,
-> `sex`  varchar(2) NOT NULL,
-> `salary`  float(9,2) NOT NULL,
-> PRIMARY KEY(`id`));
mysql> insert into user_info values 
-> ('1', '小明', 23, '男', 5200.22),
-> ('2', '小王', 24, '男', 5300.22),
-> ('3', '小美', 26, '女', 6200.32);

5. 更新表结构

mysql>alter table user_info add column `Addr`  varchar(100) NOT NULL after `salary`;
mysql>update  user_info set Addr='奉贤紫屿培训学校' where name='小明';

6. 联合查询连接功能

mysql> select a.name, a.age, a.salary, b.signin from user_info a inner join employee_tbl b  on a.name=b.name;

7. 总结

  • 库操作: 增删改查
    增:create database 数据库名字;
    删:drop database 数据库名字;
    改: use 数据库名字; 打开数据库
    查:show databases;
  • 表操作: 增删改查
    增:create table 表名(字段名 字段类型 字段属性, 字段名2.....);

    create table aa (`id` int(10)  NOT NULL Auto_increment, `name` varchar(20) NOT NULL);

    删:drop table aa;
    改:alter table aa ADD COLUMN addr varchar(10) NOT NULL AFTER name;

    alter table  aa MODIFY COLUMN `salary` float(9,2);
    alter table  aa DEL COLUMN `addr`;
    改记录
    update  aa set salary=5300.33 where name='小明';

    查:desc aa; 查表结构
    查记录: select 字段1, 字段2 .... 字段N FROM 表名;

               select * from aa; 
               select * from aa where  id=1; 
               select * from aa order by id desc; 
               select * from aa order by id asc;
               select * from aa group by name;
               select name,  count(*) from aa group by name;
               select coalesce(name, "总数:"),  SUM(signin) from aa group by name with rollup;

    8.数据表的备份和还原

    8.1 备份数据库:

    mysqldump -u root -p 数据库名字  >  备份文件.sql

    8.2 还原数据表:

    mysql -u root -p -e "create database bbs;"
    mysql -u root -p bbs < 备份文件.sql

mysql -u root -p -e "create database bbs"
mysql -u root -p bbs < 备份文件.sql

树莓派4B跑个WS2812灯带

WS2812灯带在树莓派4B上的变化

今天尝试了一下,好多代码都变化了。
现在用的基本上就是要将树莓派的RPi.GPIO库都丢了。

sudo apt purge -y RPi.GPIO
sudo pip3 install rpi_ws281x adafruit-circuitpython-neopixel
sudo python3 -m pip install --force-reinstall adafruit-blinka

然后就安装这两个库够了。
灯带的5V接树莓派5V,当然,如果灯的数量多,建议额外供电,我就8个灯的灯带,够用。
GND接树莓派GND。
信号口D+接到树莓派物理接口12号,BCM的18号口上。
然后就可以写代码测试了。

import board
from time import sleep
import neopixel

pixels = neopixel.NeoPixel(board.D18, 8)

pixels.fill((0,255,0))

pixels[0] = (255,0,0)

while True:
    for x in range(0, 8):
        pixels[x] = (255, 0, 0)
        sleep(0.1)
        pixels.fill((0,255,0))

    for x in range(0, 8):
        pixels[x] = (255, 0, 0)
        sleep(0.1)
        pixels.fill((0,255,255))

    for x in range(0, 8):
        pixels[x] = (255, 0, 0)
        sleep(0.1)
        pixels.fill((0,0,255))

    for x in range(0, 8):
        pixels[x] = (0, 255, 0)
        sleep(0.1)
        pixels.fill((255,255,127))

    for x in range(0, 8):
        pixels[x] = (0, 255, 0)
        sleep(0.1)
        pixels.fill((255,255,0))

代码非常简单,不屑注释了。

import board
from time import sleep
import neopixel

pixels = neopixel.NeoPixel(board.D18, 8)

pixels.fill((0,255,0))

这段代码是初始化的部分。
运行以下代码以导入必要的模块,并初始化带有8个LED的NeoPixel灯带,如果你的NeoPixels连接到其他引脚,别忘了更改引脚,如果灯的数量不一样,也要改。
实例化后我用了fill方法来做操作了,有三个方法如下:

  • brightness - The overall brightness of the LED
  • fill - Color all pixels a given color.
  • show - Update the LED colors if auto_write is set to False.
    一般brightness是调亮度,fill就是填充颜色,show更新颜色。

    pixels[0] = (255,0,0)

    file
    就是点亮第一个灯,颜色为红色,(255,0,0) 就是 (R,G,B)三色的定义,每个灯都可以由3种颜色组合成N多种颜色,自己配置。

    pixels.fill((0, 255, 0))

    就是全部填充绿色。
    file
    就这么简单,其他自己琢磨吧。
    哦,最后给一张特写图:
    file
    file



    嗯,就这样。开心去浪吧!

树莓派串口编程

树莓派串口编程

简单做个笔记记录一下串口编程的方法。

  1. 树莓派需要释放蓝牙所占用的的串口。
  2. 编辑/boot/config.txt 或者通过raspi-config启用串口(serial) ,编辑文件的话直接加入enable_uart=1 然后重启。
  3. 添加 dtoverlay = pi3-miniuart-bt 或者:dtoverlay = pi3-disable-bt

    基本思路

    操作示例代码

    • C 语言
      #include <stdio.h>
      #include <string.h>
      #include <errno.h>
      #include <wiringPi.h>
      #include <wiringSerial.h>
      int main ()
      {
      int serial_port ;
      char dat;
      if ((serial_port = serialOpen ("/dev/ttyS0", 9600)) < 0) /* open serial port */
      {
      fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
      return 1 ;
      }
      if (wiringPiSetup () == -1)                   /* initializes wiringPi setup */
      {
      fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
      return 1 ;
      }
      while(1){   
      if(serialDataAvail (serial_port) )
      { 
      dat = serialGetchar (serial_port);      /* receive character serially*/ 
      printf ("%c", dat) ;
      fflush (stdout) ;
      serialPutchar(serial_port, dat);        /* transmit character serially on port */
        }
      }
      }

      编译测试

      gcc -o serialtest -lwiringPi serialtest.c 
      ./serialtest

      结果:

ESP32测试脚本

ESP32 测试脚本

Micropython

from machine import Pin
from time import sleep

leds = [13, 12, 14, 27, 26, 25, 33, 32, 23, 22, 21, 19, 18, 5, 16, 17, 4, 0, 2, 15 ]
try:
    while True:
        for i in range(len(leds)):
            print(leds[i])
            i = Pin(leds[i], Pin.OUT)
            i.on()
except KeyboardInterrupt:
    print("\nCtrl-C pressed.")

树莓派超声波测距

树莓派超声波测距

超声波传感器

就是传说中的Ultrasonic传感器,学名:HC-SR04 , 某宝上非常cheap, 自己搜.

测距原理

  • 超声波距离传感器设计为使用超声波来测量源与目标之间的距离。
  • 我们之所以使用超声波,是因为超声波在短距离内相对准确,并且不会引起人耳无法听到的干扰。

特性说明

HC-SR04是用于2cm至400cm距离非接触距离测量的常用模块。
它使用声纳(如蝙蝠和海豚)以高精度和稳定的读数来测量距离。
它由超声波发射器,接收器和控制电路组成。
发射器发射短脉冲,该短脉冲被目标反射并被接收器拾取。
计算超声波信号的发送和接收之间的时间差。
使用声速和“ 速度=距离/时间 ”等式,可以轻松计算源与目标之间的距离。

引脚说明

HC-SR04超声波距离传感器模块具有四个引脚:

  • VCC – 5V,输入电源

  • TRIG –触发输入

  • 回声 –回声输出

  • GND –接地

    实际工作原理

  • 1.向TRIG输入提供触发信号,它需要至少10μS持续时间的高电平信号。

  • 2.这使模块能够发送八个40KHz超声波脉冲串。

  • 3.如果模块前面有障碍物,它将反射那些超声波

  • 4.如果信号返回,则模块的ECHO输出将在发送和接收超声信号所花费的时间内保持为高电平。脉冲宽度的范围为150μS至25mS,具体取决于障碍物与传感器之间的距离,如果没有障碍物,则脉冲宽度约为38ms。

    接线方式

    非常关键的分压步骤

    ECHO输出为5v而Raspberry Pi GPIO的输入引脚的额定电压为3.3V,因此,无法将5V直接提供给不受保护的3.3V输入引脚,除非你想把树莓派干掉...
    因此,我们得使用分压电路,使用适当的电阻将电压降至3.3V。

    以下公式可用于计算电阻值,
    “ Vout = Vin x R2 /(R1 + R2)”
    这里我用的是常用的4.7K和10K电阻做的分压电路,中间抽头给树莓派GPIO引脚,安全可靠。

    连接实物模拟图

    画图软件是frizing, 不要再私信问我了...

    计算方法

  • 距离计算
    脉冲所花费的时间实际上是超声波信号往返的时间,而我们只需要一半的时间。因此,时间被视为时间/ 2。

  • 距离=速度时间/ 2
    而海平面声速= 343 m / s或34300 cm / s
    因此,距离= 17150
    时间(单位厘米)

*校准
为了获得准确的距离读数,可以使用尺子校准输出。在下面的程序中,添加了0.5 cm的校准。
你如果不想校准也可以尝试不加,就是大致有点儿偏移量。

测试代码:

import RPi.GPIO as GPIO                    #Import GPIO library
import time                                #Import time library
GPIO.setmode(GPIO.BCM)                     #Set GPIO pin numbering 

TRIG = 23                                  #Associate pin 23 to TRIG
ECHO = 24                                  #Associate pin 24 to ECHO

print "Distance measurement in progress"

GPIO.setup(TRIG,GPIO.OUT)                  #Set pin as GPIO out
GPIO.setup(ECHO,GPIO.IN)                   #Set pin as GPIO in

while True:

  GPIO.output(TRIG, False)                 #Set TRIG as LOW
  print "Waitng For Sensor To Settle"
  time.sleep(2)                            #Delay of 2 seconds

  GPIO.output(TRIG, True)                  #Set TRIG as HIGH
  time.sleep(0.00001)                      #Delay of 0.00001 seconds
  GPIO.output(TRIG, False)                 #Set TRIG as LOW

  while GPIO.input(ECHO)==0:               #Check whether the ECHO is LOW
    pulse_start = time.time()              #Saves the last known time of LOW pulse

  while GPIO.input(ECHO)==1:               #Check whether the ECHO is HIGH
    pulse_end = time.time()                #Saves the last known time of HIGH pulse 

  pulse_duration = pulse_end - pulse_start #Get pulse duration to a variable

  distance = pulse_duration * 17150        #Multiply pulse duration by 17150 to get distance
  distance = round(distance, 2)            #Round to two decimal points

  if distance > 2 and distance < 400:      #Check whether the distance is within range
    print "Distance:",distance - 0.5,"cm"  #Print distance with 0.5 cm calibration
  else:
    print "Out Of Range"                   #display out of range

测试

python3 ultrasonic_distance_detect.py

效果很明显。

总结

反射角度如果大于15度有可能会出现值不准,如果附近噪声很大也许会有干扰,其他的没啥,很简单的一个模块,可以结合树莓派或者别的设备做一个超声波控制音量的玩意儿,树莓派爬音乐网站,播放音乐,由超声波传感器来进行检测,距离小于多少就降低音量,否则就开大音量, 自己想办法玩儿吧! 转载记得标识出处!
谢谢观看,我是骑驴玩儿漂移,甩你三条街~ 白了个白~

Live555直播

树莓派上用 Live555 直播摄像头数据

最近在群里听到有朋友推荐使用 live555 来在树莓派上进行rtsp 服务器的搭建,非常简单做个记录防忘记.
Live555是一个开源的 C++源码编写的流媒体推流软件合集,功能好多,还咩有玩儿透彻,但是你也看得懂源码的.非常激动人心.

软件包下载

链接: http://www.live555.com/liveMedia/public/

通过命令解压并执行 makefile 的生成.

tar -xf live555-latest.tar.gz
cd live/
./genMakefiles linux

编辑当前目录下面的live/testProgs/testOnDemandRTSPServer.cpp

修改这部分内容:

树莓派上创建一个 fifo 文件,先进先出管道.

mkfifo /tmp/rpicam

然后编译并安装.

make 
sudo make install

进入 testProgs 目录执行二进制文件.

./testOnDemandRTSPServer &

树莓派开启摄像头并执行:

raspivid -rot 180 -o /tmp/rpicam -f -t 0

VLC 测试或者 opencv 测试:

  1. vlc 在打开网络流的URL 里面输入设备流地址: rtsp://192.168.3.20:8554/liv0 就可以观看了.
  2. 使用 opencv 打开,自己创建一个文件:
    如图,截图中缩进层级有点儿变化,主要看后面的代码.
    图为:

    代码走一波

    # get streaming video via opencv
    import cv2
    import numpy as np
    cap = cv2.VideoCapture("rtsp://192.168.3.20:8554/liv0")
    try:
    while True:
        ret, frame = cap.read()
        if ret == True:
            smallFrame = cv2.resize(frame, (480, 240))
    
            key = cv2.waitKey(1)
            if key == 27:
                break
            cv2.imshow("small size Frame", smallFrame)
    except KeyboardInterrupt:
    print("quit")
    cap.release()
    cv2.destroyAllWindows()

    执行查看:

    python3 streaming_get_from_opencv.py

    效果如图:

    好了,还有一个我在蘑菇云参加一个 piday4fun 的活动地址在: https://github.com/piday4fun

    还楞啥,燥起来吧!!!

    转发记得标明出处, 否则小心菊花万人捅~

KiCAD 第一弹: 小白入门级

KiCAD

缘起

自从安装了 KiCAD 以后,突然发现这是一个非常棒的开源软件,好多的资源可以用,内心激动的迫不及待的想做出一个 PCB 板.手头还有一片 ATmega328P-AU 的 arduino 芯片,赶紧搜索了一下 arduino 的最小系统原理图,照猫画虎来了一遍.其实还是有多小细节要注意的.

其实发现还是有 arduino Uno 的一个器件的.还需要慢慢摸索.这次的硬核马拉松我觉得我要败了..

发现

树莓派上竟然也可以跑 kicad, 而且安装极其简单,简单的不像话....

sudo apt-get update 
sudo apt-get -y install kicad
kicad &

就好了.就打开了,第一次可能有点儿卡顿,但是一旦跑起来那种丝般柔顺的感觉真的很舒服~
突然就爱上了这个软件.虽然相比 AD 可能还有很大差距,但是毕竟是开源软件,还有那么多用户,github 也是人气满满.强烈推荐大家尝试一下..
我发现我需要学习的东西太多了,我一直感觉自己是一个小白一样的存在, 看了很多资料还是前面看完后面就不记得了....
哎,人到中年不如狗系列啊!
好了,不吐槽了.还是要有满满的正能量才可以, 继续啃啃技术材料吧~
我是骑驴玩儿漂移,一个胖胖的爱玩儿树莓派或者是喜欢嘚瑟的胖纸!