Jupyter怎么装到Rocky Linux 8上

Jupyter是Python数据分析的一个重要工具,除非你对图表没什么要求,或者习惯了命令行。否则大多会用到这个工具。

Rocky Linux是红帽家族的一个开源免费发行版。两者加到一起,就是一个字:稳。

首先,你可以用Root用户登录。然后执行如下命令:

jupyter notebook --generate-config

生成配置文件,程序会提醒你配置文件保存在哪里的。

比如我这里是:

/root/.jupyter/jupyter_notebook_config.py

然后,编辑这个配置文件。

第一步,让Jupyter可以远程访问,因为默认都是localhost Only。

c.NotebookApp.ip = ‘*’

第二步,让Jupyter换个端口,这个看自己,不是必选项。

c.NotebookApp.port = 8888

改完配置文件后,还得设置Jupyter需要密码登录,不然你的小秘密都被人看光光了。

执行:

jupyter notebook password

敲两遍密码,成功。密码文件会保存在这里。

/root/.jupyter/jupyter_notebook_config.json

最后执行:

jupyter notebook –allow-root

就可以启动Jupyter了。

我是王文文,欢迎关注IoT前哨站和我交流。

树莓派挖矿教程之Chia篇

随着数字货币的兴起,不少人又开始了挖矿生涯。

除了经典的显卡和CPU挖矿以外,其实业内还有一种硬盘挖矿的方法。这就是号称“绿色比特币”的Chia。

目前的价格大概是4500-5500RMB一枚。

它倒是不怎么耗电,但很耗硬盘。所以你接个树莓派也可以挖。

基本配置:

树莓派4B(至少4GB内存版本)

64位系统(不一定要RaspberryPi OS)

大容量硬盘一块

步骤:

先到chia.net下载工具。

找到树莓派的版本,目前官方测过的主要就是树莓派4B。

直接安装或者下载后安装都可以。

安装完启动该程序。

别忘了24个助记词。

把P好的文件导入。当然,如果你不嫌慢,在树莓派上生成Plots也可以。

如果硬盘挂载顺利,可以看到现成的Plot文件。

导入以后你可以在标签栏里看到它们。

在网络同步完成之后,你就可以开始挖了。

Chia挖矿的入门,就是这么简单。

如何让树莓派Pico支持LoRaWAN

LoRaWAN是由LoRa联盟推出的一个低功耗广域网规范,这一技术可以为电池供电的无线设备提供区域、国家甚至全球的网络。

它瞄准了物联网中的一些核心需求,比如安全的双向通讯、移动化和本地服务。该技术无需复杂配置,即可以让智能设备实现无缝的互操作,给物联网领域的用户、开发者和企业自由操作权限。

使用合理的LoRa天线,你可以通过网关将电池供电的传感器连到互联网,信号覆盖半径大约15公里。缺点是可用带宽将以字节为单位,而不是以兆字节甚至千字节为单位。

一个Adafruit RFM95W LoRa无线电装置连接到树莓派Pico

Arduino LoRa库的作者Sandeep Mistry为树莓派Pico搞定了LoRa和以太网支持。

目前他的库能让Semtech SX1276无线电模块更好的工作在Pico和其它RP2040芯片的开发板上。

当然,这意味着像Adafruit的RFM95W、LoRa FeatherWing这样的模块,也可以获得很好的支持。

LoRaWAN覆盖情况

要使用LoRaWAN启用的Pico,你(的设备)需要在LoRa网关覆盖的范围内。幸运的是,有一个名叫“The Things Network”的LoRaWAN网络,它几乎覆盖全球。

关于The Things Network的视频:

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

这取决于你当前所处的地理位置,很可能你已经在覆盖范围内了。比如英国境内的LoRa网络情况(如图)。

一个LoRaWAN基站的成本在几千美元的日子已经一去不复返了。现在你可以花75英镑买个LoRa网关。

注:The Things Network 是 LoRaWAN 行业里著名的 Network Server 提供方,许多国外的厂家,都是默认连接 TTN 的平台。

作为 LoRa 联盟董事会成员,TTN 现在已经在全球90多个国家和地区部署了3000多个基站,这个数字还在飞速增长中。TTN一直秉承的 “Let’s build this thing together”的开放文化也吸引了超过3万名开发者加入 TTN 社区。

获取源码

如果你已经设置并可以使用树莓派Pico工具链,请确保你的 pico-sdk 是最新的。如果没有,你应该首先设置C/C++ SDK,然后再从GitHub中获取项目。

$ git clone --recurse-submodules https://github.com/sandeepmistry/pico-lorawan.git

$ cd pico_lorawan

PICO_SDK_PATH 在继续操作之前,请确保做好设置。举例来说,如果你要在一个树莓派上构建相关应用,你要先运行 pico_setup.sh 脚本,或者按照我们的指示入门指南。

先设置好环境变量。

$ export PICO_SDK_PATH = /home/pi/pico/pico-sdk

之后,你可以准备构建库和示例应用程序。但是在执行此操作之前,我们需要做另外两件事:在要存储数据的云基础架构上进行配置,并将LoRa无线电模块连接到Raspberry Pi Pico。

设置一个应用程序

The Things Network 目前正在从V2迁移到V3堆栈。由于我的家庭网关是几年前设置的,因此我仍在使用V2软件,尚未迁移。

因此,我将构建一个V2风格的应用程序。但如果你用公共网关或自己构建网关,则可构建V3样式的应用程序。

同理,你可以根据下面的内容逐步完成操作。请注意,对于新的V3堆栈,有一个单独的网络控制台,外观可能有所不同。

地址:https://account.thethingsnetwork.org/users/authorize?client_id=ttn-console&redirect_uri=https:%2F%2Fconsole.thethingsnetwork.org%2Foauth%2Fcallback&response_type=code&state=_wyzCpGx9A

当新网关覆盖范围内的任何LoRa设备将其数据包接收和发送到上游的“The Things Network”时,除非数据包有其它地方可去,否则数据包将被丢弃。换句话说,“The Things Network”需要知道网关接收的数据包路由到哪里。

为了提供此信息,我们首先需要在The Things Network Console中创建一个应用程序 。

然后你需要做的就是输入唯一的Application ID字符串(可以是任何内容)。控制台将生成一个Application EUI和一个默认的Access Key,我们将通过它们,将设备注册到我们的应用程序中。

一旦我们注册了应用程序,我们要做的就是将单个设备(以后可能有多个设备)注册到该应用程序,以便后端知道从该设备路由数据包的位置。

注册设备

可以从控制台的应用程序页面注册我们的设备。

设备ID是易于识别的字符串,用于标识我们的远程设备。

由于Adafruit的RFM9W功能板在包装袋中有像无线入网号那种唯一标识符的贴纸,因此我们可以使用它在字符串后附加以唯一地标识我们的树莓派Pico,因此最终得到类似pico-xy-xy-xy-xy-xy-xy的设备ID名称。

我们还需要生成一个Device EUI2,这是一个64位的唯一标识符。这里我们同样可以使用标签上的唯一标识符,只不过这次我们可以用两个前导零 0000xyxyxyxyxyxyxy填充它,以便生成我们的Device EUI。你也可以使用pico_get_unique_board_id()来生成Device EUI。

相关链接:https://github.com/sandeepmistry/pico-lorawan/blob/main/examples/default_dev_eui/main.c

如果你要在注册后查看“设备”页面,则需要设置Application EUI 2Application Key 2来让开发板与LoRa网络通信。准确地说,是让网络正确地将数据包从你的开发板路由到你的应用程序。

在面包板上接线

现在我们已经设置了云后端,接下来需要做的是将Pico连接到LoRa扩展板。不幸的是,RFM95W breakout 与面包板的连接并不友好 —— 比如这个项目,需要访问电路板两侧的无线电引脚。在这种情况下,板子的分接头宽度有点太大了(对于标准面包板而言)。

幸运的是,这并不是什么大问题,但是你需要准备一束公对母跳线以及面包板。继续接通RFM95W模块和Raspberry Pi Pico。接线板上的引脚和你的Pico之间的映射应该如下所示:

PicoRP20401SX1276 ModuleRFM95W Breakout
3V3 (OUT)VCCVIN
GNDGNDGNDGND
Pin 10GP7DIO0G0
Pin 11GP8NSSCS
Pin 12GP9RESETRST
Pin 14GP10DIO1G1
Pin 21GP16 (SPI0 RX)MISOMISO
Pin 24GP18 (SPI0 SCK)SCKSCK
Pin 25GP19 (SPI0 TX)MOSIMOSI
物理引脚,RP2040引脚,SX1276模块和RFM95W扩展板之间的映射
注:这些引脚是库的默认引脚,可以在软件中更改。

构建和部署软件

现在,我们已经在云上建立了后端,并且我们已经物理上“构建”了无线电,我们可以构建和部署LoRaWAN应用程序。该库提供的示例应用程序之一将从RP2040微控制器上的传感器读取温度,并通过LoRaWAN无线电将其定期发送到你的Things Network应用程序。

void internal_temperature_init() {
    adc_init();
    adc_select_input(4);
    adc_set_temp_sensor_enabled(true);
}

float internal_temperature_get() {
    float adc_voltage = adc_read() * 3.3f / 4096;
    float adc_temperature = 27 - (adc_voltage - 0.706f) / 0.001721f;

    return adc_temperature;
}

继续,进入签出的otaa_temperature_led示例应用程序目录。这个例子用到了OTAA,所以我们需要Device EUI,Application EUI和Application Key。

$ cd examples/otaa_temperature_led/

打开config.h文件,在你喜欢的编辑和更改REGION,DEVICE_EUI,APP_EUI,并APP_KEY在网络控制台中显示的值。该代码期望使用(默认)字符串格式,十六进制数字之间没有空格,而不是字节数组表示形式。

在你喜欢的编辑器中打开config.h文件,并将REGION、DEVICE_EUI、APP_EUI和APP_KEY更改为网络控制台中显示的值。该字符串默认是中间没有空格的十六进制数字,而不是字节数组。

#define LORAWAN_REGION          LORAMAC_REGION_EU868
#define LORAWAN_DEVICE_EUI      "Insert your Device EUI"
#define LORAWAN_APP_EUI         "Insert your Application EUI"
#define LORAWAN_APP_KEY         "Insert your App Key"
#define LORAWAN_CHANNEL_MASK    NULL

我当前位于英国,LoRa广播频率为868MHz。

因此我要将区域设置为LORAMAC_REGION_EU868。

如果你在美国,则使用915MHz,因此需要将区域设置为LORAMAC_REGION_US915。

编辑config.h文件之后,就可以继续构建示例应用程序了。

$ cd ../..
$ mkdir build
$ cd build
$ cmake ..
$ make

如果一切顺利的话,你应该有一个UF2文件在build/examples/otaa_temperature_led/的目录,名字是pico_lorawan_otaa_temperature_led.uf2

现在,你可以按照常规方式将此UF2文件加载到树莓派Pico上。

先接好你的Raspberry Pi Pico开发板和Micro USB电缆,然后再将电缆的另一头插入有集成开发环境的电脑,按住Pico上的BOOTSEL按钮。插入后,松开按钮。

桌面上将会弹出一个名为RPI-RP2的磁盘。

双击将其打开,然后将UF2文件拖放到里面。如果遇到问题,请参阅《入门指南》第4章以 获取 更多信息。

Pico现在将运行LoRaWAN应用程序,如果需要,可以通过打开与Pico的USB串行连接来查看一些调试信息。打开终端窗口并启动 minicom

$ minicom -D /dev/ttyACM0

传送资料

但是,你需要转向Network控制台来查看真实的信息。你应该能看到一个初始连接消息,后面跟着一些帧。每一帧代表一个温度测量值通过LoRaWAN网关,从你的Pico发送到The Things Network网络应用。

有效负载值是Raspberry Pi Pico内部温度传感器以十六进制形式测得的温度。

这有点超出本文的讨论范围,但是你现在可以添加一个解码器和集成功能,使你可以将数据从十六进制解码为人类可读的数据,然后将其保存到数据库中。

为了说明你可以在此处执行的操作的强大功能,请转到应用程序的“有效载荷格式”标签,然后在“解码器”框中输入以下Javascript,然后向下滚动并点击绿色的“保存有效载荷功能”按钮。

function Decoder(bytes, port) {
 
  var decoded = {};
  decoded.temp = bytes[0];
  
  return decoded;
}

返回“数据”选项卡,你应该看到现在以十六进制表示的有效负载已经以摄氏温度为后缀。我们的简单解码器已将有效负载提取并将其转换回Javascript对象。

发送命令

除了发送温度数据之外,该示例应用程序还让你可以直接从The Things Network控制台切换Raspberry Pi Pico上的LED。

进入网络控制台的设备页面,在Downlink Payload框中输入“01”,并点击“发送”按钮。然后切换到Data选项卡。你应该会看到一个“Download scheduled”行,如果继续观察,你应该会看到下行的字节。

当这种情况发生时,你树莓派Pico上的LED应该会亮起!返回网络控制台并在有效载荷箱中输入“00”将(最终)关闭Pico的LED。

请记住,LoRaWAN是远程的,但带宽很低。你不要期望下行命令能即时响应。

接下来还有什么

OTAA示例应用程序是一个非常好的框架,你可以在此基础上构建它,它允许你获取数据并通过LoRa将其发送到云端,还可以从云端向支持LoRa的Pico发送命令。

地址:https://github.com/sandeepmistry/pico-lorawan/tree/main/examples/otaa_temperature_led

小结

可以在树莓派论坛上找到对Pico开发的支持。还有一个(非官方的)Discord频道,很多活跃在社区的人似乎都在那里玩。

地址:https://discord.com/invite/avzEvd6Euv

关于文档的反馈应该作为一个问题发布到GitHub上的pico-feedback仓库,或者直接发布到它关注的相关仓库。

所有的文档,以及其他帮助和链接,都可以在入门页面上找到。

如果你不知道未来它在哪里,你总是可以从你的Pico找到它。如果你要访问相关页面,只需按住你Pico上的BOOTSEL按钮,把它插到你的笔记本电脑或树莓派上,然后释放按钮。最后打开RPI-RP2盘符,单击INDEX.HTM文件。

它将把你带到入门页。

可将照片自动同步到苹果电脑的PiPhoto

用传统数码相机拍完照总是要导照片,但要把SD卡上的照片导到苹果电脑上并不容易。一般都得要USB转接头什么的。

如果拍完照,能直接通过网络,自动同步SD卡里的照片到电脑上,那该多好啊。

别担心,PiPhoto可以帮你实现这个需求。

自动化解决方案

一名名叫Lou Kratz的国外网友几乎每个周末都花很多时间在镜头前记录自己的冒险经历。但是他受不了每次都手动导入,所以他发明了PiPhoto,使流程自动化。

视频地址:

从视频中你可以看到,Lou Kratz用了一个非常简单的方案。只需将SD卡插入Raspberry Pi中,照片就会自动上传到计算机上。

树莓派上的LED用于显示状态:

在处理过程中,绿色指示灯将开始闪烁。绿色常亮表示作业成功,红色闪烁表示作业失败。

相关代码:

https://github.com/IoToutpost/pi-photo-sync

安装步骤:

下载代码,在树莓派上运行:
sudo ./install.sh

创建一个新的配置文件,并对其进行编辑。:
sudo cp config/piphoto.conf.example /etc/piphoto.conf

需要设置的变量是:
mount_point – SD卡的安装位置(应与以下udev规则中的位置相匹配。)
run_as_user – 用于运行同步程序的用户。
sync_command – 运行什么命令来同步照片。(请参见上面的目标)。

作者最新的改进可以让Raspberry Pi按日期整理所上传的照片,具体用法可参考代码。

让鸿蒙智能家居开发板与AWS IoT云完美连通

本期直播简介:

使用鸿蒙智能家居开发板连通AWS IoT云平台


直播课程大纲:

1、AWS IoT平台介绍

2、AWS IoT SDK介绍

3、移植AWS IoT SDK到HarmonyOS

4、实现HarmonyOS接入AWS IoT

三大隐藏福利:

1、讲师在线答疑互动

2、一个小时两轮抽奖

3、进群掌握一手资讯

讲师介绍:

连志安——广州旗点智能科技有限公司创始人

从事物联网行业开发,擅长物联网、嵌入式、Linux、HarmonyOS、RTOS等技术。

书籍《物联网——嵌入式开发实战》

直播抽奖:

免费报名+到会看直播,赢取HarmonyOS官方联名T恤、HarmonyOS官方开发板(HiSpark Wi-Fi IoT 智能家居套件)

(中奖用户所填写收件人姓名、电话、地址需为真实信息,信息仅用于工作人员联系用户发放奖品。)

适合人群:

想要学习以下知识的人群:

1、HarmonyOS网络通信

2、利用HarmonyOS连接云平台

3、AWS IoT平台接入

扫码进群:

扫描下方二维码,加入AWS技术交流群

(如无法进群,请添加小助手微信:xiao51cto,备注“AWS加群”)

触碰即盛放的“宝莲灯”——Arduino创意作品

编者注:这是一个名叫JiříPraus的外国小哥实现的Arduino创意作品,实际上是“郁金香”,但看着太像中国神话故事里的“宝莲灯”了。

轻轻抚摸就会绽放,它的六个花瓣将缓慢打开并照耀出彩虹般的光。当花瓣闭合时,它们会产生令人难以置信的带有叶子图案的光。

所需材料:

Arduino Nano R3
SG90微型伺服电机
TTP223触摸传感器
1mm黄铜丝
2mm黄铜管
0.3mm绝缘铜线
WS2812 5050 NeoPixel LED灯 x 7
白色SMD 1206 LED x 30

附注:如何焊接黄铜

https://davidneat.wordpress.com/2015/05/03/a-quick-guide-to-soldering-brass/amp/

推杆如何与花瓣一起运动

当推杆向上移动时,它将连杆和花瓣向下拉。当它向下移动时,它拖着连杆,将花瓣闭合。

单片花瓣的构成:

花瓣由黄铜细条组成,花瓣内有5个白色LED和同一根导线构成的“静脉”结构。

相同的花瓣,一共要做6个。否则它们在关闭时不会构成漂亮的郁金香形状,甚至会卡住。

相关代码:


#include <Adafruit_TiCoServo.h>
#include "SoftPWM.h"

#define NEOPIXEL_PIN A0
#define TOUCH_SENSOR_PIN 2

#define SERVO_PIN 9
//#define SERVO_OPEN 1750
#define SERVO_OPEN 1650
#define SERVO_SAFE_MIDDLE 1000
#define SERVO_CLOSED 775

#define RED 0
#define GREEN 1
#define BLUE 2

float currentRGB[] = {0, 0, 0};
float changeRGB[] = {0, 0, 0};
byte newRGB[] = {0, 0, 0};

#define MODE_SLEEPING 0
#define MODE_BLOOM 3
#define MODE_BLOOMING 4
#define MODE_BLOOMED 5
#define MODE_FADE 6
#define MODE_FADING 7
#define MODE_FADED 8
#define MODE_FALLINGASLEEP 9

#define MODE_RAINBOW 90

byte mode = MODE_FADED;

byte petalPins[] = {3, 4, 5, 6, 10, 11};

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(7, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ400);
Adafruit_TiCoServo servo;

int servoChange = 1; // open
int servoPosition = SERVO_SAFE_MIDDLE;

void setup() {
  Serial.begin(115200);
  pixels.begin();
  servo.attach(SERVO_PIN, SERVO_CLOSED, SERVO_OPEN);

  pinMode(TOUCH_SENSOR_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(TOUCH_SENSOR_PIN), _touchISR, RISING);

  randomSeed(analogRead(A7));
  SoftPWMBegin();

  pixelsUnifiedColor(pixels.Color(0, 0, 0));
  //pixelsUnifiedColor(pixels.Color(255, 70, 0));

  prepareCrossFade(140, 70, 0, 140);
  servo.write(servoPosition);
}

int counter = 0;
byte speed = 15;

void loop() {
  boolean done = true;
  switch (mode) {
    case MODE_BLOOM:
      prepareCrossFadeBloom(500);
      changeMode(MODE_BLOOMING);
      break;

    case MODE_BLOOMING:
      done = crossFade() && done;
      done = openPetals() && done;
      done = petalsBloom(counter) && done;
      if (done) {
        changeMode(MODE_BLOOMED);
      }
      break;

    case MODE_FADE:
      //prepareCrossFade(0, 0, 0, 800);
      changeMode(MODE_FADING);
      break;

    case MODE_FADING:
      done = crossFade() && done;
      done = closePetals() && done;
      done = petalsFade(counter) && done;
      if (done) {
        changeMode(MODE_FADED);
      }
      break;

    case MODE_FADED:
      //prepareCrossFade(140, 70, 0, 140);
      changeMode(MODE_FALLINGASLEEP);
      break;

    case MODE_FALLINGASLEEP:
      done = crossFade() && done;
      done = closePetals() && done;
      if (done) {
        changeMode(MODE_SLEEPING);
      }
      break;

    case MODE_RAINBOW:
      rainbow(counter);
      break;
  }

  counter++;
  delay(speed);
}

void changeMode(byte newMode) {
  if (mode != newMode) {
    mode = newMode;
    counter = 0;
  }
}

void _touchISR() {
  if (mode == MODE_SLEEPING) {
    changeMode(MODE_BLOOM);
  }
  else if (mode == MODE_BLOOMED) {
    changeMode(MODE_FADE);
  }
}

// petals animations

boolean petalsBloom(int j) {
  if (j < 250) {
    return false; // delay
  }
  if (j > 750) {
    return true;
  }
  int val = (j - 250) / 2;
  for (int i = 0; i < 6; i++) {
    SoftPWMSet(petalPins[i], val);
  }
  return false;
}

boolean petalsFade(int j) {
  if (j > 510) {
    return true;
  }
  for (int i = 0; i < 6; i++) {
    SoftPWMSet(petalPins[i], (510 - j) / 2);
  }
  return false;
}

// animations

void prepareCrossFadeBloom(unsigned int duration) {
  byte color = random(0, 5);
  switch (color) {
    case 0: // white
      prepareCrossFade(140, 140, 140, duration);
      break;
    case 1: // red
      prepareCrossFade(140, 5, 0, duration);
      break;
    case 2: // blue
      prepareCrossFade(30, 70, 170, duration);
      break;
    case 3: // pink
      prepareCrossFade(140, 0, 70, duration);
      break;
    case 4: // orange
      prepareCrossFade(255, 70, 0, duration);
      break;
  }
}

void rainbow(int j) {
  uint16_t i;
  byte num = pixels.numPixels() - 1;
  pixels.setPixelColor(pixels.numPixels() - 1, 100, 100, 100);

  for (i = 0; i < num; i++) {
    pixels.setPixelColor(i, colorWheel(((i * 256 / num) + j) & 255));
  }
  pixels.show();
}

// servo function

boolean openPetals() {
  if (servoPosition >= SERVO_OPEN) {
    return true;
  }
  servoPosition ++;
  servo.write(servoPosition);
  return false;
}

boolean closePetals() {
  if (servoPosition <= SERVO_CLOSED) {
    return true;
  }
  servoPosition --;
  servo.write(servoPosition);
  return false;
}

// utility function

void pixelsUnifiedColor(uint32_t color) {
  for (unsigned int i = 0; i < pixels.numPixels(); i++) {
    pixels.setPixelColor(i, color);
  }
  pixels.show();
}

void prepareCrossFade(byte red, byte green, byte blue, unsigned int duration) {
  float rchange = red - currentRGB[RED];
  float gchange = green - currentRGB[GREEN];
  float bchange = blue - currentRGB[BLUE];

  changeRGB[RED] = rchange / (float) duration;
  changeRGB[GREEN] = gchange / (float) duration;
  changeRGB[BLUE] = bchange / (float) duration;

  newRGB[RED] = red;
  newRGB[GREEN] = green;
  newRGB[BLUE] = blue;

  Serial.print(newRGB[RED]);
  Serial.print(" ");
  Serial.print(newRGB[GREEN]);
  Serial.print(" ");
  Serial.print(newRGB[BLUE]);
  Serial.print(" (");
  Serial.print(changeRGB[RED]);
  Serial.print(" ");
  Serial.print(changeRGB[GREEN]);
  Serial.print(" ");
  Serial.print(changeRGB[BLUE]);
  Serial.println(")");
}

boolean crossFade() {
  if (currentRGB[RED] == newRGB[RED] && currentRGB[GREEN] == newRGB[GREEN] && currentRGB[BLUE] == newRGB[BLUE]) {
    return true;
  }
  for (byte i = 0; i < 3; i++) {
    if (changeRGB[i] > 0 && currentRGB[i] < newRGB[i]) {
      currentRGB[i] = currentRGB[i] + changeRGB[i];
    }
    else if (changeRGB[i] < 0 && currentRGB[i] > newRGB[i]) {
      currentRGB[i] = currentRGB[i] + changeRGB[i];
    }
    else {
      currentRGB[i] = newRGB[i];
    }
  }
  pixelsUnifiedColor(pixels.Color(currentRGB[RED], currentRGB[GREEN], currentRGB[BLUE]));
  /*
    Serial.print(currentRGB[RED]);
    Serial.print(" ");
    Serial.print(currentRGB[GREEN]);
    Serial.print(" ");
    Serial.print(currentRGB[BLUE]);
    Serial.println();
  */
  return false;
}

uint32_t colorWheel(byte wheelPos) {
  // Input a value 0 to 255 to get a color value.
  // The colours are a transition r - g - b - back to r.
  wheelPos = 255 - wheelPos;
  if (wheelPos < 85) {
    return pixels.Color(255 - wheelPos * 3, 0, wheelPos * 3);
  }
  if (wheelPos < 170) {
    wheelPos -= 85;
    return pixels.Color(0, wheelPos * 3, 255 - wheelPos * 3);
  }
  wheelPos -= 170;
  return pixels.Color(wheelPos * 3, 255 - wheelPos * 3, 0);
}
Credits

将树莓派打造成RFID和NFC的识别装置

用华为和苹果的朋友,应该知道自己的手机上基本都带NFC支付功能。

实际上NFC相关的场景不只是支付,还涵盖我们生活中的方方面面。比如IoT前哨站之前发过的一篇:DIY带数据的NFC“袖扣”

NFC(近场通信)基于RFID(射频识别)标准,两者都允许设备从被动令牌或电子标签接收数据(这意味着它不需要外部电源即可工作)。

市场上有现成的RFID和NFC识别设备出售,但可定制化程度不高。不过熟悉树莓派的朋友,可以凭借WaveShare的RFID/NFC扩展板,DIY一个更极客的识别装置。

和树莓派适配后的成品

开始之前,你需要一个能跑Raspberry Pi OS Lite(Buster)的树莓派,还有一个WaveShare NFC扩展板(大约人民币几十块)。

登录系统后,先更新系统。

sudo apt -y update && sudo apt -y upgrade

启用串行接口

该扩展版能够通过三个不同的接口进行通信:I2C,SPI和UART。

我们这里使用UART,因为它演示起来最简单。首先运行sudo raspi-config,进入“接口选项”,然后选择“串行接口”。

当系统询问你是否要登录控制台时,请选择“否”。当询问你是否要启用串行接口时,请选择“是”。

你需要立即重启,这将允许WaveShare HAT通过串行接口与我们的Raspberry Pi对话。

Waveshare HAT包含许多设置。请务必阅读说明!

配置并安装扩展板

如上所述,我们可以通过更改扩展板本身的某些物理开关来选择不同的接口。默认情况下,我们可以将其配置为UART / Serial,但具体接法最好到以下网址核对:

https://www.waveshare.com/wiki/PN532_NFC_HAT#Raspberry_Pi_examples

一般I1和I0处的跳线均应短接“ L”,D16和D20应短接,在DIP开关上,除RX和TX外,所有其他器件均应关闭。

仔细检查,然后将板子插到树莓派GPIO口上,启动。

然后执行如下命令:

sudo apt install rpi.gpio p7zip-full python3-pip
pip3 install spidev pyserial

wget https://www.waveshare.com/w/upload/6/67/Pn532-nfc-hat-code.7z
7z x Pn532-nfc-hat-code.7z

在尝试任何操作之前,需要编辑示例文件,以便我们使用UART。请根据自身要求将其注释或启用。

cd ~/raspberrypi/python
nano example_get_uid.py

pn532 = PN532_UART(debug=False, reset=20)

拿RFID令牌来测试一下

试试看!

如下所示启动示例代码:
python3 example_get_uid.py

如果一切顺利,屏幕将会显示与扩展板连接的信息。

现在,你可以将RFID令牌放在标有“ NFC”的HAT区域上。十六进制数字会开始在屏幕上滚动。这意味着,你的令牌已被检测到!

每个RFID令牌都有唯一的编号,因此可以用来标识不同人员的身份。

但是,该扩展板的功能远不止于此,因为它还支持NFC,并且可以与MIFARE Classic等通用标准进行通信,该标准允许卡上存储1kB的存储空间。

对应的example_dump_mifare.py文件在同一目录中(请确保你已正确设置串行连接)。

更进一步

现在,你可以读取RFID和NFC令牌上的唯一标识符了。

如前所述,如果你用的是MIFARE或NTAG2标准,还可以将数据写到卡上。

examples文件夹包含一些C程序,你可以试一下。

在卡上读取和写入少量数据,可以产生一些有趣的项目。在2018年的电磁场节上,整个游戏都是基于查找物理位置并使用MIFARE卡注册玩家的存在来进行的。

智能手机还可以使用NFC交换任何形式的数据,以及更多可能。

来自:Raspberrypi.org

编译:王文文

【鸿蒙直播】从零开发鸿蒙小游戏App

2020年11月4日(周三,晚20:00),我将为大家做一场鸿蒙App开发的直播,主题是《从零开发鸿蒙小游戏App》。我会从零开始手把手地带领大家开发一款运行在鸿蒙设备上的、曾经风靡全球的小游戏。我会对编写的每一行代码进行讲解。我们采用边做边学的方式,在做中学,在学中做,在直播过程中完成一个小游戏App的所有功能。

>>>点击免费报名<<<

讲师介绍:

就目前而言,鸿蒙App开发可用的平台有三个:智慧屏、智能手表、运动手表。

如果我们开发的是智慧屏或智能手表上的App,那么目前华为还没有开放基于X86的本机模拟器,因此,需要将编写的代码发送到远程的ARM处理器以运行代码,在本机上只能预览运行结果,而无法在本机上运行和调试代码。

如果我们开发的是运动手表上的App,那么既可以使用本机的预览器Previewer来预览代码的运行效果,也可以使用本机的模拟器simulator来运行和调试代码。在运动手表这个平台上,相关的设备和开发工具是最成熟、最完善的,给开发者的体验已经很棒了!

本次直播主要是在运动手表上使用JavaScript编程语言完成项目的编写,直播后会尽快将Java版的项目代码共享给大家。

学习有礼:

参加HarmonyOS公开课,抽官方定制周边! 

官方定制T恤等你来拿!还有机会赢取HarmonyOS官方开发板(HiSpark Wi-Fi IoT 智能家居套件)

直播前导课程:https://edu.51cto.com/course/25054.html

鸿蒙运动手表呼吸训练项目源代码下载:https://harmonyos.51cto.com/posts/1076

用树莓派驱动的青蛙泡泡机

吹泡泡机可能大家小时候都玩过,加满肥皂液,接上电源以后,它就会自动吹出泡泡。

现在有了树莓派,可以把它改成互联网控制的自动泡泡机了。

改造之前,泡泡机由手动开关控制,该开关可打开或关闭青蛙体内的电机。如果你想看到电机驱动青蛙吹出泡泡,则需要自己轻触此开关。

几个国外的创客制作了这款自动泡泡机,该机器由树莓派供电和控制,并且可以通过互联网启动。

他们选择了青蛙形的泡泡机,但你可以根据自己的喜好重新调整。改造使用两节AA电池运行的模型会更容易。

在解剖了“塑料两栖朋友”之后,他们通过继电器模块将其电机连接到Raspberry Pi。他们分享了相关的技术细节,可将继电器模块连接到Raspberry Pi的GPIO引脚。

相关技术介绍:

https://tutorials-raspberrypi.com/raspberry-pi-control-relay-switch-via-gpio

现在,我们可以用代码打开和关闭青蛙体内的马达。

通过在:

https://remo.tv/join/rffrwxr

这个地址登录,命令Raspberry Pi打开泡泡机的开关。

为了让互联网泡泡迷们看到一键劳动的成果,我们设置了Raspberry Pi摄像头模块,并将其构建的装置连接到机器人流媒体平台remo.tv。

别忘了加肥皂水。

用料清单:

泡泡机(最好是用两节AA电池运行的那种)
树莓派
5V继电器模块
Raspberry Pi摄像头模块
Remo.tv帐户
跳线

剩下的问题是:最好的泡沫肥皂配方是什么?

来自:​Raspberrypi.org

编译:王文文

如何为树莓派设置SSH的双因素认证

如今,启用双因素身份验证(2FA)来增强帐户的安全性变得越来越普遍。

但是你可能会好奇怎么在Raspberry Pi上启用2FA。当你通过Secure Shell(SSH)远程访问树莓派时,系统将要求你先输入动态验证码。

通过SSH访问Raspberry Pi

很多人在家中将Raspberry Pi用作文件或媒体服务器。随着Raspberry Pi 4的发布,这种情况已经相当普遍,它配备了USB 3.0和千兆以太网。

如果你打算将Raspberry Pi塞到电视后面或其他地方,这意味着你需要在没有监视器,键盘或鼠标的情况下启用S​​ecure Shell(SSH)进行远程访问。

但是,出门在外也想访问文件的需求很常见,所以从Internet访问Raspberry Pi是一件有风险的事。

如果你要对Internet开放你的树莓派服务器,那肯定要增加一些安全性,比如使用基于时间的一次性密码(TOTP)或启用双因素身份验证(2FA )。

什么是双因素身份验证?

双因素身份验证是额外的保护层。是除了密码之外,还需要另一条信息才能登录。

如果说第一个因素是“你知道的东西”,那第二个因素将基于“你拥有的东西”(例如智能手机),就像生物特征信息一样。

我们将继续设置,并将智能手机用作保护Raspberry Pi的第二个因素。

更新操作系统

你应该做的第一件事是确保你的Raspberry Pi OS保持最新。如果你正在运行不够新的操作系统,则可以在命令行操作:

$ sudo apt-get update
$ sudo apt-get full-upgrade

启用安全的Shell​

Raspbian操作系统在启动时禁用了SSH服务器,如果我们希望通过SSH访问Raspberry Pi,则需要启用它。

启用S​​SH最简单的方法是先进Raspbian桌面,找到菜单,然后选择“首选项”,Raspberry Pi配置。接下来,选择“Interfaces”选项卡,然后单击按钮启用SSH,再点“确定”。

你还可以在命令行启用它:

$ sudo systemctl enable ssh 
$ sudo systemctl start ssh

另外,你可以用raspi-config启用S​​SH ,如果你是首次安装操作系统,也可以在写SD卡时启用S​​SH 。

启用挑战响应

接下来,我们需要告诉SSH守护程序启用“挑战响应”密码。继续打开SSH配置文件:

$ sudo nano /etc/ssh/sshd_config

通过将ChallengeResponseAuthentication从默认的no更改为yes来启用挑战响应。

重启SSH服务

$ sudo systemctl restart ssh

在你的笔记本电脑上打开一个终端,确保你仍然可以SSH到你的树莓派——尽管你还没有被提示输入2FA代码。在这个阶段检查是否一切正常是明智的。

安装双因素身份验证App

你需要做的第一件事是将应用程序下载到手机,该应用程序将生成TOTP。Google身份验证器是最常用的一种。它可用于AndroidiOSBlackberry,甚至在GitHub上也有该应用程序的开源版本。

App Store中的Google Authenticator

因此,请继续在你的手机上安装Google Authenticator或另一个2FA应用程序,例如Authy。然后,在Raspberry Pi上安装Google Authenticator PAM模块。

$ sudo apt install libpam-google-authenticator

现在我们在手机和Raspberry Pi上都安装了2FA,已经准备好进行配置。

配置两因素身份验证

现在,你应该在Raspberry Pi上运行Google Authenticator而不使用sudo来生成QR码:

$ google-authenticator

之后,你可能需要调整“终端”窗口的大小,以便正确显示QR码。不幸的是,它比标准的80个字符略宽。

google-authenticator生成的QR码

此刻先不要下一步! 在执行其他任何操作之前,你应该复制紧急代码并将其放在安全的地方。

这些代码使你可以在丢失手机的情况下访问Raspberry Pi,并关闭2FA。没有它们话,如果你丢失或破坏了用于身份验证的设备,则将无法通过SSH访问Raspberry Pi。

接下来,在我们继续使用Raspberry Pi上的Google Authenticator之前,请在手机上打开Goog​​le Authenticator应用,点击右上角的加号(+),然后点击“扫描二维码”。

手机将询问你是否允许该应用访问你的相机;选择“是”,相机镜头将打开,将二维码放置在屏幕上的绿色框中。

使用Google Authenticator应用程序扫描QR码

手机应用程序识别出QR码后,就会添加你的新帐户,并会自动开始生成TOTP代码。

Google Authenticator应用中的TOTP

你的手机将每三十秒生成一次新的TOTP密码。但是,直到我们完成你在Raspberry Pi上所做的工作,此验证码才有用。

切换到终端窗口,并在询问Google Authenticator是否更新你的.google_authenticator文件时回答“Y” 。

然后回答“Y”以禁止多次使用相同的身份验证令牌,“N”以增加时间偏移窗口,“Y”以限制速率,以防止暴力攻击。

接下来,我们要做的就是启用2FA。

启用双因素身份验证

我们将使用Linux可插拔身份验证模块(PAM),它为应用程序和服务提供动态身份验证支持,以便在Raspberry Pi的SSH上添加2FA。

现在我们需要配置PAM以添加2FA:

$ sudo nano /etc/pam.d/sshd

将必需的auth pam_google_authenticator.so添加到文件顶部。你可以在显示@include common-auth的行上方或下方执行此操作。

编辑/etc/pam.d/sshd

由于我希望在输入密码后提示输入验证码,因此我在@include行之后添加了这一行。如果要在输入密码之前提示输入验证码,则应将其添加到@include行之前。

现在重新启动SSH守护程序:

$ sudo systemctl restart ssh

接下来,在笔记本电脑上打开一个终端窗口,然后尝试用SSH访问Raspberry Pi。

收尾

如果一切都按计划进行,那么当你通过SSH访问Raspberry Pi时,输入密码后应该提示你输入TOTP。

用SSH访问我的Raspberry Pi

继续打开手机上的Google身份验证器,然后在出现提示时输入六位验证码。登录Raspberry Pi。

无论是SSH还是SCP,设备的安全性都大大提高了。

现在,你已经在手机上装好Google Authenticator应用程序,可以为重要的服务和网站(例如Google,Twitter,Amazon等)启用2FA了,因为大多数网站都已支持双因素验证。

作者:Alasdair Allan

来自:Raspberrypi.org