“紫密”的前辈Enigma是怎么工作的

在密码学史中,恩尼格玛密码机(Enigma)是一种具有影响力的加密与解密文件密码机。该密码机采用了一系列相似的转子机械加解密机制,为对称加密算法的流加密奠定了基础。

恩尼格玛密码机外观看起来是一个装满了复杂而精致元件的盒子。然而,当我们打开它时,可以将其分解为相对简单的几个部分。最核心的部分包括键盘、显示器和三个转子。键盘用于输入明文,显示器则用于显示加密后的密文。三个转子负责将明文转换为密文的过程。

在恩尼格玛密码机中,当按下键盘上的某个键时,与该字母对应的密文会在显示器上亮起。这是因为转子内部集成了6条线路(在实物中是26条),可以将键盘的信号对应到显示器不同的小灯上去。例如,如果按下字母’a’键,灯’B’就会亮起,这意味着字母’a’被加密成了字母’B’。

为了提高加密的复杂性,恩尼格玛密码机还采用了三个转子的旋转机制。每个转子都可以独立旋转,并具有26个不同的位置。当输入一个字母时,转子会旋转一定的角度,使得相同的字母在加密时对应不同的密文。这种机制增加了破译的难度,使得恩尼格玛密码机在二战期间成为了一种难以破解的加密工具。

此外,为了使消息更难以破译,恩尼格玛密码机还采用了空格和标点符号的省略机制。这意味着在加密过程中,空格和标点符号不会被包括在内,从而使得密文更难以被解读。

总体而言,恩尼格玛密码机的工作原理是通过键盘输入明文,经过三个转子的转换和加密算法的处理,最终在显示器上显示密文。这种加密方式具有很高的复杂性和难以破解的特点,因此在密码学史上具有重要的地位。

然而,尽管恩尼格玛密码机在二战期间被广泛使用并被认为是安全的加密工具,但在二战末期,英国的密码学家通过不懈的努力成功地破解了恩尼格玛密码机。这一事件成为了密码学史上的一个重要里程碑,也为我们提供了一个宝贵的教训:随着技术的发展和进步,没有任何一种加密方式是绝对安全的。

下面用C语言来实现这个加密过程,代码比较简单,仅供参考。可自己完善。

先来一段明文:Send troops to Poland today(今日出兵波兰),中间空格要去掉。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define MAX_CHARS 26

// 交换两个字符
void swap(char *a, char *b) {
    char temp = *a;
    *a = *b;
    *b = temp;
}

// 随机打乱字符数组
void shuffle(char *arr, int n) {
    for (int i = n - 1; i > 0; i--) {
        int j = rand() % (i + 1);
        swap(&arr[i], &arr[j]);
    }
}

int main() {
    // 生成字母表
    char a[MAX_CHARS];
    for (int i = 0; i < MAX_CHARS; i++) {
        a[i] = 'a' + i;
    }

    // 复制并打乱字母表
    char b[MAX_CHARS];
    memcpy(b, a, MAX_CHARS);
    shuffle(b, MAX_CHARS);

    // 建立对应密码表 (这里使用数组代替字典,下标作为索引)
    char dict[MAX_CHARS][2];
    for (int i = 0; i < MAX_CHARS; i++) {
        dict[i][0] = a[i];
        dict[i][1] = b[i];
    }

    // 待加密字符串
    char word[] = "sendtroopstopolandtoday";
    char encrypted[MAX_CHARS];

    printf("加密前: %s\n", word);

    // 加密
    int j;
    for (int i = 0; i < strlen(word); i++) {
        for (j = 0; j < MAX_CHARS; j++) {
            if (word[i] == dict[j][0]) {
                encrypted[i] = dict[j][1];
                break;
            }
        }
    }
    encrypted[strlen(word)] = '\0';

    printf("加密后: %s\n", encrypted);

    return 0;
}

结果是:

加密前: sendtroopstopolandtoday
加密后: dgncsuffjdsfjfylncsfclr

先别高兴太早,这只是单张表,很容易被破解。

为了提升破解者的难度,下面用两张表来混合加密。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define MAX_CHARS 26

// 交换两个字符
void swap(char *a, char *b) {
    char temp = *a;
    *a = *b;
    *b = temp;
}

// 随机打乱字符数组
void shuffle(char *arr, int n) {
    for (int i = n - 1; i > 0; i--) {
        int j = rand() % (i + 1);
        swap(&arr[i], &arr[j]);
    }
}

int main() {
    // 初始化随机数种子
    srand(time(NULL));

    // 生成字母表
    char a[MAX_CHARS];
    for (int i = 0; i < MAX_CHARS; i++) {
        a[i] = 'a' + i;
    }

    // 复制并打乱字母表两次
    char b[MAX_CHARS], c[MAX_CHARS];
    memcpy(b, a, MAX_CHARS);
    memcpy(c, a, MAX_CHARS);
    shuffle(b, MAX_CHARS);
    shuffle(c, MAX_CHARS);

    // 建立对应密码表 (使用二维数组表示)
    char dict1[MAX_CHARS][2], dict2[MAX_CHARS][2];
    for (int i = 0; i < MAX_CHARS; i++) {
        dict1[i][0] = a[i];
        dict1[i][1] = b[i];
        dict2[i][0] = a[i];
        dict2[i][1] = c[i];
    }

    // 待加密字符串
    char word[] = "sendtroopstopolandtoday";
    char encrypted[100];  // 确保足够大

    printf("加密前: %s\n", word);

    // 加密
    int j;
    for (int i = 0; i < strlen(word); i++) {
        for (j = 0; j < MAX_CHARS; j++) {
            if (word[i] == dict1[j][0]) {
                encrypted[i] = i % 2 == 0 ? dict1[j][1] : dict2[j][1];
                break;
            }
        }
    }
    encrypted[strlen(word)] = '\0';

    printf("加密后: %s\n", encrypted);

    return 0;
}

结果是:

加密前: sendtroopstopolandtoday
加密后: yazkownmfuomfmiqzkomhqx

双表混合法,即第一个字符是使用第一个映射表加密,第二个字符使用第二张映射表来进行加密,这可以使加密的安全度提高很多,也比较接近Enigma机的工作原理。

下面来讲明文的还原方式。

根据前面获得的两张映射表,将它们全部反转。

第一张表:

{‘a’: ‘s’, ‘b’: ‘t’, ‘c’: ‘r’, ‘d’: ‘h’, ‘e’: ‘b’, ‘f’: ‘w’, ‘g’: ‘q’, ‘h’: ‘j’, ‘i’: ‘p’, ‘j’: ‘e’, ‘k’: ‘v’, ‘l’: ‘i’, ‘m’: ‘g’, ‘n’: ‘z’, ‘o’: ‘n’, ‘p’: ‘f’, ‘q’: ‘m’, ‘r’: ‘u’, ‘s’: ‘y’, ‘t’: ‘o’, ‘u’: ‘d’, ‘v’: ‘c’, ‘w’: ‘l’, ‘x’: ‘a’, ‘y’: ‘x’, ‘z’: ‘k’}

第二张表:

{‘a’: ‘q’, ‘b’: ‘l’, ‘c’: ‘g’, ‘d’: ‘k’, ‘e’: ‘a’, ‘f’: ‘v’, ‘g’: ‘j’, ‘h’: ‘y’, ‘i’: ‘p’, ‘j’: ‘z’, ‘k’: ‘x’, ‘l’: ‘n’, ‘m’: ‘c’, ‘n’: ‘d’, ‘o’: ‘m’, ‘p’: ‘t’, ‘q’: ‘s’, ‘r’: ‘w’, ‘s’: ‘u’, ‘t’: ‘h’, ‘u’: ‘o’, ‘v’: ‘f’, ‘w’: ‘b’, ‘x’: ‘e’, ‘y’: ‘r’, ‘z’: ‘i’}

反转第一张表:

{‘s’: ‘a’, ‘t’: ‘b’, ‘r’: ‘c’, ‘h’: ‘d’, ‘b’: ‘e’, ‘w’: ‘f’, ‘q’: ‘g’, ‘j’: ‘h’, ‘p’: ‘i’, ‘e’: ‘j’, ‘v’: ‘k’, ‘i’: ‘l’, ‘g’: ‘m’, ‘z’: ‘n’, ‘n’: ‘o’, ‘f’: ‘p’, ‘m’: ‘q’, ‘u’: ‘r’, ‘y’: ‘s’, ‘o’: ‘t’, ‘d’: ‘u’, ‘c’: ‘v’, ‘l’: ‘w’, ‘a’: ‘x’, ‘x’: ‘y’, ‘k’: ‘z’}

反转第二张表:

{‘q’: ‘a’, ‘l’: ‘b’, ‘g’: ‘c’, ‘k’: ‘d’, ‘a’: ‘e’, ‘v’: ‘f’, ‘j’: ‘g’, ‘y’: ‘h’, ‘p’: ‘i’, ‘z’: ‘j’, ‘x’: ‘k’, ‘n’: ‘l’, ‘c’: ‘m’, ‘d’: ‘n’, ‘m’: ‘o’, ‘t’: ‘p’, ‘s’: ‘q’, ‘w’: ‘r’, ‘u’: ‘s’, ‘h’: ‘t’, ‘o’: ‘u’, ‘f’: ‘v’, ‘b’: ‘w’, ‘e’: ‘x’, ‘r’: ‘y’, ‘i’: ‘z’}

然后把密文填进去,就可以出来明文了。

这里还是用代码来实现:

#include <stdio.h>
#include <string.h>

int main() {
    char mm[] = "yazkownmfuomfmiqzkomhqx";
    char dict3[26][2] = {
        {'s', 'a'}, {'t', 'b'}, {'r', 'c'}, {'h', 'd'}, {'b', 'e'}, {'w', 'f'}, {'q', 'g'}, {'j', 'h'}, {'p', 'i'}, {'e', 'j'},
        {'v', 'k'}, {'i', 'l'}, {'g', 'm'}, {'z', 'n'}, {'n', 'o'}, {'f', 'p'}, {'m', 'q'}, {'u', 'r'}, {'y', 's'}, {'o', 't'},
        {'d', 'u'}, {'c', 'v'}, {'l', 'w'}, {'a', 'x'}, {'x', 'y'}, {'k', 'z'}
    };
    char dict4[26][2] = {
        {'q', 'a'}, {'l', 'b'}, {'g', 'c'}, {'k', 'd'}, {'a', 'e'}, {'v', 'f'}, {'j', 'g'}, {'y', 'h'}, {'p', 'i'}, {'z', 'j'},
        {'x', 'k'}, {'n', 'l'}, {'c', 'm'}, {'d', 'n'}, {'m', 'o'}, {'t', 'p'}, {'s', 'q'}, {'w', 'r'}, {'u', 's'}, {'h', 't'},
        {'o', 'u'}, {'f', 'v'}, {'b', 'w'}, {'e', 'x'}, {'r', 'y'}, {'i', 'z'}
    };

    char word[strlen(mm) + 1];
    word[strlen(mm)] = '\0';

    for (int i = 0; i < strlen(mm); i++) {
        if (i % 2 == 0) {
            for (int j = 0; j < 26; j++) {
                if (mm[i] == dict3[j][0]) {
                    word[i] = dict3[j][1];
                    break;
                }
            }
        } else {
            for (int j = 0; j < 26; j++) {
                if (mm[i] == dict4[j][0]) {
                    word[i] = dict4[j][1];
                    break;
                }
            }
        }
    }

    printf("明文是:%s\n", word);

    return 0;
}

明文是:sendtroopstopolandtoday

实际的Enigma机工作起来要比这个复杂很多,但基本原理类似。有兴趣的朋友可以深入研究。

DrissionPage,不用给爬虫装驱动了

DrissionPage是一个基于Python的网页自动化库,它结合了selenium和requests的优点,可以轻松实现网页的自动化操作。DrissionPage的主要特点是其简洁的API设计,使得用户可以很容易地编写代码来实现网页自动化。

特点

  • 简洁的API设计:DrissionPage的API设计非常简洁,用户无需深入了解Selenium的底层实现,也能进行复杂的网页交互。
  • 结合了selenium和requests的优点:既可以实现动态网页的自动化,也可以实现静态网页的自动化。
  • 灵活性:支持多种选择器,包括CSS选择器、XPath选择器等,适应不同的网页结构。
  • 强大的等待机制:内置智能等待,确保元素在操作前已经加载完成。
  • 支持多种浏览器:DrissionPage支持多种浏览器,包括Chrome、Firefox等。

 

​安装

安装DrissionPage非常简单,只需要通过pip安装即可:

pip install drissionpage
 

初始化

在使用DrissionPage之前,需要先进行初始化。可以使用以下代码进行初始化:

from DrissionPage import MixPage
page = MixPage(‘chrome’)
 

这里我们使用Chrome浏览器进行初始化,你也可以使用其他浏览器,例如Firefox。

打开网页

初始化之后,可以使用open_url方法来打开一个网页。

例如,我们可以使用以下代码来打开百度首页:

page.open_url(‘https://www.baidu.com’)
 

查找元素

在打开网页之后,我们通常需要查找网页中的元素。DrissionPage提供了多种方法来查找元素,例如ele、eles、css、xpath等。例如,我们可以使用以下代码来查找百度首页的搜索框:

search_box = page.ele(‘#kw’)
 

这里我们使用ele方法来查找id为kw的元素。

操作元素

在找到元素之后,我们可以对元素进行各种操作,例如输入文本、点击等。例如,我们可以使用以下代码来在百度搜索框中输入文本并搜索:

search_box.send_keys(‘Python’)
page.ele(‘#su’).click()
 

这里我们使用send_keys方法来输入文本,使用click方法来点击搜索按钮。

获取元素信息

在找到元素之后,我们还可以获取元素的各种信息,例如文本、属性等。例如,我们可以使用以下代码来获取百度搜索结果的第一条结果的标题:

title = page.ele(‘.t a’).text
print(title)
 

此外,DrissionPage支持复杂的网页交互,例如填写表单、点击按钮等:

# 填写表单
browser.find_element_by_name(‘username’).send_keys(‘my_username’)
browser.find_element_by_name(‘password’).send_keys(‘my_password’)

# 点击登录按钮
browser.find_element_by_xpath(‘//button[@type=”submit”]’).click()
 

其他示例

DrissionPage可以用于各种网页操作,下面是一些常见的使用示例:

# 处理下拉菜单
browser.find_element_by_id(‘dropdown’).click()
browser.find_element_by_xpath(‘//option[@value=”option-value”]’).click()

# 滚动到页面底部
browser.scroll_to_bottom()

# 获取当前页面的URL
current_url = browser.get_current_url()

# 下拉刷新
page.execute_script(‘window.scrollTo(0, document.body.scrollHeight)’)

# 上传文件
upload_button = page.ele(‘#upload’)
upload_button.send_keys(‘path/to/your/file’)

 

工作原理

DrissionPage的工作原理非常简单。它首先使用requests库来请求网页,然后使用selenium库来加载网页。在加载网页之后,就可以使用selenium的方法来查找元素、操作元素等。

高级用法

DrissionPage还支持多窗口和多标签页操作、自定义等待、处理JavaScript弹窗等高级功能:

切换到新的标签页

browser.open_new_tab()

 

自定义等待

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
wait = WebDriverWait(page.driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, ‘some_id’)))
 

这里我们使用selenium的WebDriverWait和expected_conditions来实现自定义等待。

处理JavaScript弹窗

page.driver.switch_to.alert.accept()
 

这里我们使用switch_to.alert.accept()来处理JavaScript弹窗。

总结

DrissionPage是一个功能强大且易于使用的Python库,它简化了网页自动化操作,使得即使是编程新手也能快速上手。通过本文的介绍,相信你已经对DrissionPage有了基本的了解,并且能够开始使用它来完成你的网络爬虫项目。

附录

  • DrissionPage的相关文档:https://gitee.com/g1879/DrissionPage
  • selenium官方文档:https://www.selenium.dev/documentation/en/
  • requests官方文档:https://requests.readthedocs.io/en/m

智能门铃助理 — ESPBell

ESPBell是一个基于ESP12F模块的智能门铃项目。它使用ESPBell-Lite开发板,该开发板包含ESP8266芯片、摄像头、扬声器和麦克风。https://mp.weixin.qq.com/cgi-bin/readtemplate?t=tmpl/video_tmpl&vid=wxv_3251263471233613825

功能包括:

  • 实时视频传输
  • 双向语音通话
  • 人体检测
  • 触摸按钮
  • 远程控制

使用方法如下:

  1. 下载项目代码并安装依赖项。
  2. 将ESPBell-LITE开发板连接到电脑。
  3. 编译并烧录代码到开发板。
  4. 按照说明配置 Wi-Fi 连接。

优势包括:

  • 使用ESP8266芯片,具有较高的性能和低功耗。
  • 集成了摄像头、扬声器和麦克风,可实现实时视频传输、双向语音通话和人体检测等功能。
  • 支持触摸按钮和远程控制,使用方便。

不足之处包括:

  • 开发板的价格相对较高。
  • 视频传输的质量受网络环境的影响。

总体而言,该项目是一个功能强大且易于使用的智能门铃项目。它适合家庭、办公室和其他场所使用。

以下是该项目的部分亮点:

  • 使用ESP8266芯片,具有较高的性能和低功耗,可满足实时视频传输、双向语音通话和人体检测等功能的需求。
  • 集成了摄像头、扬声器和麦克风,可实现丰富的功能。
  • 支持触摸按钮和远程控制,使用方便。

该项目具有良好的开发潜力,可以进一步扩展功能,例如:

  • 添加更多传感器,例如 PIR 传感器、门磁传感器等,实现更智能的功能。
  • 支持云端存储,实现视频录像和回放。
  • 支持 AI 识别,实现人脸识别、车辆识别等功能。

源代码:

https://github.com/IoToutpost/ESPBell-LITE
https://file.daihuo.qq.com/mp_cps_goods_card/v57/index.html

用树莓派Pico W做蓝牙遥控车

不然树莓派Pico W刚放出来那会,官方只对Wi-Fi做了支持,并未启用蓝牙功能。但这个小片片上有英飞凌的CYW43439无线模块,蓝牙、Wi-Fi都支持的。

经过漫长的等待,2023年6月,官方终于腾出手让这小片片功能全部释放。

你现在不需要再外接HC-05等其它模块,只需要原来的一片Pico W,就可以通过C语言或MicroPython来启用蓝牙了。

蓝牙在嵌入式领域有多重要,多好使,估计物联网和应用电子的从业者能跟你讲半天。

这次就让Kevin McAleer这位树莓派Pico W老粉,用MicroPython编程来给大家实践一下。

从蓝牙基础,一直跟你讲到蓝牙控制小车。深入浅出,精打实招。

https://mp.weixin.qq.com/s/EZic0V6Uba93gPiqRdGTBg

相关代码:

https://github.com/IoToutpost/pico_ble_remote

用树莓派Pico和气体传感器保护厨房

当你在厨房烹饪食物,又跑去刷剧,玩游戏,取快递……

食物正在加热,没人看着,锅烧焦了怎么办?着火了怎么办?

无人看管的烹饪是迄今为止厨房火灾的主要原因。

你可能需要有个东西来帮你盯一下。

这个小东西主要是由树莓派Pico和传感器构成的。

先说开发板,虽然该项目是基于Raspberry Pi Pico构建的,但你可以使用任何与RP2040兼容的电路板创建它。

该项目中使用的Grove-HCHO传感器可检测空气VOCs(挥发性有机化合物)的气体浓度。比如:甲醛和苯。

相关链接:

https://wiki.seeedstudio.com/Grove-HCHO_Sensor/

它是如何工作的?

通过在Raspberry Pi Pico上运行Edge Impulse的Sensor Fusion软件,它可以从气体,温度和湿度传感器读取数据。然后数据通过神经网络模型计算,会判断当前的厨房是否处于安全状态。

是的,要更准确的判断厨房安全状态,你需要更多传感器配合。

Edge Impulse相关链接:

https://studio.edgeimpulse.com/

这里有相关视频来引导你完成软件下载、设置和部署。如果你有兴趣构建自己的厨房监视器,可以照着完成。

经过AI训练,它可以检测厨房的三种状态:空闲,正常烹饪和非正常燃烧。

隐藏在炉子上方风扇罩中的传感器

除了烹饪,从新房子到新家具,也都会存在危害健康的挥发性有机化合物(比如甲醛)。如果你在家里检测到高浓度的挥发性有机化合物,那么你要尽快通风来保证安全。

相关链接:

用Phew在Pico W上构建登录系统

Home Assistant 加 Pico W 改进车库门

树莓派Pico如何用好定时器

在树莓派Pico上跑BASIC程序

Pico SDK — 树莓派Pico起步

树莓派Pico W控制玩具车

树莓派Pico怎么接DHT11温湿度传感器

树莓派Pico W迷你火星车

用Arduino IDE给Pico W开发应用

树莓派Pico上跑TinyML音频分类

用Rust语言来开发树莓派Pico

树莓派Pico的CircuitPython入门

用Pico W做个手机遥控的车库门

太阳能驱动的Pico W在线气象站

Pico W搭网站并显示访问者IP

通过MicroPython控制Pico W上的板载LED

基于树莓派Pico的机器学习

在树莓派Pico上运行“毁灭战士”

用树莓派Pico制作的无人机PiWings

如何让树莓派Pico支持LoRaWAN

长者为你开启树莓派Pico的I/O世界

在树莓派Pico上播放《Bad Apple》

在树莓派Pico上用BBC Micro模拟器玩游戏

用Arduino做一个自动割草机

这个项目中,我们将用Arduino制作一个自动割草机。该机器可以自动修剪院子里长高的草。如果有障碍物,它会自动改变方向,有助于减少人力。

本文提供了项目的基本概述,以及制作Arduino割草机器人所需的组件。提供了电路原理图和Arduino源代码,以便简化组装和编程过程。

注意:这个项目不是玩具,它包含锋利的刀片。如果不小心使用,可能会造成严重的伤害。不要让它无人看管,刀片应正确固定。操作前检查一下。

材料清单

我们需要以下组件:

1、 Arduino UNO
2、 L293D电机驱动盾
3、 超声波传感器HC-SR04
4、 超声波传感器外壳/支架
6、 直流减速电机 x4
7、 BLDC电机100KV
8、 舵机SG-90
9、 ESC模块
10、舵机测试仪
11、3针滑动开关
12、X型十字支架
13、机器人底盘
14、11.1V锂电池

什么是割草机器人(割草机)?

割草机器人是一种用于自动修剪和维护草坪的机器人设备。这些机器人使用传感器和算法来导航和修剪草坪,并且可以根据草坪的生长速度或特定的时间表来编程修剪草坪。一些割草机器人还配备了诸如障碍物检测、防盗保护和通过智能手机应用程序远程控制等功能。它们近年来越来越受欢迎,因为可以节省割草的时间和精力。

电路和连接

源代码/程序

AFMotor Library:
https://github.com/adafruit/Adafruit-Motor-Shield-library

NewPing Library:
https://github.com/microflo/NewPing

需要编译到Arduino UNO开发板中的代码:

#include <AFMotor.h>  
#include <NewPing.h>
#include <Servo.h> 
 
#define TRIG_PIN A0 
#define ECHO_PIN A1 
#define MAX_DISTANCE 200 
#define MAX_SPEED 190 
#define MAX_SPEED_OFFSET 20
 
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE); 
 
AF_DCMotor motor1(1, MOTOR12_1KHZ); 
AF_DCMotor motor2(2, MOTOR12_1KHZ);
AF_DCMotor motor3(3, MOTOR34_1KHZ);
AF_DCMotor motor4(4, MOTOR34_1KHZ);
Servo myservo;   
 
boolean goesForward=false;
int distance = 100;
int speedSet = 0;
 
void setup() {
 
  myservo.attach(10);  
  myservo.write(115); 
  delay(2000);
  distance = readPing();
  delay(100);
  distance = readPing();
  delay(100);
  distance = readPing();
  delay(100);
  distance = readPing();
  delay(100);
}
 
void loop() {
 int distanceR = 0;
 int distanceL =  0;
 delay(40);
 
 if(distance<=15)
 {
  moveStop();
  delay(100);
  moveBackward();
  delay(300);
  moveStop();
  delay(200);
  distanceR = lookRight();
  delay(200);
  distanceL = lookLeft();
  delay(200);
 
  if(distanceR>=distanceL)
  {
    turnRight();
    moveStop();
  }else
  {
    turnLeft();
    moveStop();
  }
 }else
 {
  moveForward();
 }
 distance = readPing();
}
 
int lookRight()
{
    myservo.write(50); 
    delay(500);
    int distance = readPing();
    delay(100);
    myservo.write(115); 
    return distance;
}
 
int lookLeft()
{
    myservo.write(170); 
    delay(500);
    int distance = readPing();
    delay(100);
    myservo.write(115); 
    return distance;
    delay(100);
}
 
int readPing() { 
  delay(70);
  int cm = sonar.ping_cm();
  if(cm==0)
  {
    cm = 250;
  }
  return cm;
}
 
void moveStop() {
  motor1.run(RELEASE); 
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
  } 
  
void moveForward() {
 
 if(!goesForward)
  {
    goesForward=true;
    motor1.run(FORWARD);      
    motor2.run(FORWARD);
    motor3.run(FORWARD); 
    motor4.run(FORWARD);     
   for (speedSet = 0; speedSet < MAX_SPEED; speedSet +=2) 
   {
    motor1.setSpeed(speedSet);
    motor2.setSpeed(speedSet);
    motor3.setSpeed(speedSet);
    motor4.setSpeed(speedSet);
    delay(5);
   }
  }
}
 
void moveBackward() {
    goesForward=false;
    motor1.run(BACKWARD);      
    motor2.run(BACKWARD);
    motor3.run(BACKWARD);
    motor4.run(BACKWARD);  
  for (speedSet = 0; speedSet < MAX_SPEED; speedSet +=2) 
  {
    motor1.setSpeed(speedSet);
    motor2.setSpeed(speedSet);
    motor3.setSpeed(speedSet);
    motor4.setSpeed(speedSet);
    delay(5);
  }
}  
 
void turnRight() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);     
  delay(500);
  motor1.run(FORWARD);      
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);      
} 
 
void turnLeft() {
  motor1.run(BACKWARD);     
  motor2.run(BACKWARD);  
  motor3.run(FORWARD);
  motor4.run(FORWARD);   
  delay(500);
  motor1.run(FORWARD);     
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}  

测试

上传代码后,你可以把机器人带到野外,也许在高草地区。高草地区可以是一个很好的测试选择。

打开机器人上的开关,确保电源为Arduino板提供正确的电压,并且所有组件都正确连接。通过手动控制机器人的运动来测试机器人的电机,确保机器人运动平稳准确。

测试机器人的传感器,在其路径上放置障碍物,并确保能避开它们。此外,检查传感器的范围和灵敏度,以确保机器人可以检测到草的存在。

谷歌Sheets和ESP8266构建的考勤系统

用户刷卡后,系统会与包含用户列表的谷歌表单进行核对。

如果用户获得授权,LCD上会显示用户的姓名、接入类型和自定义留言,并发出“嘟”的一声。系统还将考勤数据记录在谷歌Sheet中,供以后查看和分析。

开始之前,你得有一个Google账户,且所在网络可以顺利登录Google。

https://mp.weixin.qq.com/cgi-bin/readtemplate?t=tmpl/video_tmpl&vid=wxv_2903425061842321412

主要材料:

RFID RC522

https://www.aliexpress.us/item/2251832760608169.html

esp8266

https://www.aliexpress.us/item/2251832470086446.html

lcd1602

https://www.aliexpress.us/item/2251832499297742.html

breadboard

https://www.aliexpress.us/item/2251832028089611.html

相关源码:

https://github.com/unreeeal/ESP/tree/master/ESP-RFID-GOOGLE

注:这里ESP32和ESP8266的使用场景是差不多的,两者都可以实现类似功能。

谁进我屋了之“无线门户报警器”

前面我们讲到了简易门户报警器的实现。

相关链接:

这次来做一个升级,实现网络报警。

项目需求:

当有人打开门或没关上门时,Micro:bit马上通过无线网络向你报警。

实现原理:

Micro:bit上面有个磁力计,这里可以设定每2秒测量一次磁场强度。当磁场低于某个特定水平(阈值)时,它会发送一个无线信号“door open”。如果磁性读数超过阈值,则会发送“door closed”。

当警报器Micro:bit收到“door closed”信息时,其 LED显示屏上会显示一个勾号。 当收到“door open”无线电讯息时,它会显示一个大叉并发出警报声。

所需材料:

Micro:bit 2个
电池包 2个
磁铁 1个
万能胶或类似工具,用以将磁铁固定在门上,并将Micro:bit固定在门框上。
可选的蜂鸣器或扬声器
鳄鱼夹引线

门户端代码:

from microbit import *
import radio
radio.config(group=17)
compass.calibrate()
radio.on()

while True:
    if button_a.was_pressed():
        display.scroll(compass.get_field_strength())
    if compass.get_field_strength() < 100000:
        display.show(Image.DIAMOND_SMALL)
        radio.send('door open')
    else:
        display.clear()
        radio.send('door closed')
    sleep(2000)

报警端代码:

from microbit import *
import music
import radio
radio.config(group=17)
radio.on()

while True:
    message = radio.receive()
    if message:
        if message == 'door open':
            display.show(Image.NO)
            music.play(["C4:4"])
        if message == 'door closed':
            display.show(Image.YES)

离线编辑器:

在线编辑器:

https://makecode.microbit.org/#editor

https://python.microbit.org/v/3?l=zh-CN

进阶:

1、按下Micro:bit上的按键A,以帮助校准磁力的最佳阈值。在MakeCode中将其设置为100 microteslas,与在Python中的10000 nanoteslas相同。
2、使用多个Micro:bit来发送不同的无线电消息(例如“back door open”)以追踪多门的状态。
3、使用变量来计算门保持打开状态的时间。

谁进我屋了之“简易门户警报器”

这是写给物联网新手的教程,熟手如果好奇也可以看一下。

有人来过你的房间吗?使用Micro:bit,电池组和磁铁,你可以让门发出警报,以提醒有人闯入。

关于Micro:bit:

Micro:bit是一个卡片大小的计算机,它有一个LED显示屏、按键、传感器和一些输入/输出引脚,可以在Scratch和Python程序的控制下,与你的世界交互。

原理:

Micro:bit上面内建了一个compass sensor,称为磁力计。 你可以使用它来测量地球的磁场,以作为指南针-或感应到附近的磁场强度!

代码:

当磁力强度感应低于200,就显示愤怒的表情。

当按钮A按下时,显示当前磁力强度。

如果用Python的话,这样写:

# Python uses nanoteslas to measure magnetism.
# Experiment with different numbers depending on the
# strength of your magnet, which you can read by 
# pressing button A.

from microbit import *

while True:
    if button_a.was_pressed():
        display.scroll(compass.get_field_strength())
    if compass.get_field_strength() < 200000:
        display.show(Image.ANGRY)

做法:

将磁铁固定在门上,然后将写入开门警报器程序的Micro:bit靠近它,固定在墙上。

接好电源。这样一个简单的报警装置就做好啦。

进阶:

1、添加声音警报。

2、使用一个变量来计算门被打开的次数,这里需要添加一个程序来感应门是否被打开或关闭。

3、创建一个定时器计算门被打开多长时间

好了,拿去玩吧。

本文主要内容来自:

microbit.org

相关视频:

谁进我屋了之“简易门户警报器” (qq.com)