本文目录一览:
詹士 发自 凹非寺
量子位 | 公众号 QbitAI
除了吃灰,Kindle还能干什么?
不是泡面盖,而是你的智能管家,每天出门前,提醒你天气情况、即将到达的包裹。
这玩意有人已经造出来了。
一位做前端与设计的美国小哥,将一块10多年前的老Kindle改造成了一块能显示日历、天气、网购包裹、家务提醒的智能显示板。
整个过程中,无需再买任何硬件,操作流程也简单。
在reddit上,该项目已获得500+个赞,有网友表示自己已改造了好几块了。
具体如何操作的?
往下看。
成本比树莓派还便宜之所以上手改造,始于小哥希望在手机之外能有个显示工具挂墙上,随时提醒自己时间日程、天气、快递哪天到……等等信息。
考虑到Kindle价格比树莓派还便宜,基于Linux操作系统,易破解调试,且墨水屏比发光屏幕更自然地融入家中环境,他果断从网上花30美元购买了一台二手Kindle4,约合211.5人民币。
但仍有三个问题要解决:
Kindle会自动进入睡眠状态并显示屏保程序;
如果想更新屏幕数据,每次浏览器页面都会重新加载,观感很差;
Kindle浏览器还有一些难看又冗余的元素,比如标题、URL栏,且并不好看;
基于上述原因,小哥设计了一套解决思路:
部署一个能获取网页屏幕截图的服务器,让Kindle作为终端显示屏,每分钟下载一次该截图。
鉴于市面上已有部分平台提供定时截屏服务,但收费不低,小哥决定自己编写一个小型服务器,使用 Puppeteer截图,再依靠ImageMagick转换格式。
带着这一规划,他开动了。
先是设置图像服务器。
小哥自己编写了代码并在Heroku创建一个免费账户,在平台填好项目名,就能一键部署。(现已开源,人人可用,链接见文末)
退出前,别忘了记下URL。
接着,回到Kindle本体。
连上WiFi,对其进行越狱,网上相关教程有很多,跟着步骤走就行,注意下载文件及流程与版本号相符就行。(相关资料已附在参考链接)
然后,安装USBNetwork插件。复制.bin文件进去就行,接着通过Settings设置->更新Kindle,完成安装。
断开Kindle与电脑的连接,通过设备键盘,输入;debugOn
回车,启动调试模式。
继续打开键盘,输入~usbNetwork,回车,等待几秒,再输入;debugOff,回车。
重新连接电脑。在桌面打开命令行,输入ssh root@192.168.15.244并回车。然后输入默认密码——mario。
现在,你已经可对Kindle进行编程了。
接着,调整驱动从「只读」变成「可写」状态,输入mntroot rw并回车。
再输入下方代码,创建图像下载脚本,让你能打开并编辑。
nano /mnt/us/script.sh
在编辑器中输入下面代码,注意「Insert_your_URL_from_step_2_here」部分,替换为前面第二步复制的URL:
curl Insert_your_URL_from_step_2_here -o status.pngeips -ceips -ceips -g status.png
上述代码中,第一行是保存图像到status.png文件,两个eips-c命令是为了清除屏幕,最后一行为显示图像。
完成后,输入control-O,再输入control-X,保存并退出编辑器。
然后运行脚本测试一下,输入/script.sh,就能看见屏幕上能看见图像显示。
最后一步, 设置定时程序,让其每分钟刷新。
由于Kindle系统与其他Linux设备一样,其中有个cron工具,可按计划定时运行。
只需打开配置文件:
nano /etc/crontab/root
将下面命令添加到底部:
*****/mnt/us/script.sh
同样,输入⌃O,回车,再输入⌃X,最后重启:
/etc/init.d/cron restart
BINGO!搞定!
很多人都在魔改墨水屏上述魔改的小哥名叫Matt Healy,是一位设计师兼前端工程师。
他目前也是一家SaaS平台的联合创始人,主要为其他企业提供用户/客户喜好研究与需求洞察服务,闲暇时间,他还做了个自己的主页。
不止他一人,其实改造墨水屏设备的玩家还有不少。
比如一位芬兰程序员Kimmo做了个墨水屏天气显示器,每天出门前提醒自己穿什么衣服合适。
这两天,他的改造帖子冲上了HackerNews前3。
更早时候,还有一位荷兰小哥,女票是英国文学老师,他用Kindle做了个文学时钟送给了对方。
当程序启动后,Kindle将会以文学名著段落显示当前时间,此外,还能猜测该句来自哪本书。按下翻书按钮,屏幕就会显示答案,深得女票喜爱。
最后问问, 你觉得Kindle还能用来干什么?
参考链接:[1]https://matthealy/Kindle[2]https://wikileread/wiki/Kindle_Hacks_Information#Jail_break_JB[3]https://blog.adafruit/2021/01/29/your-next-smart-home-device-is-a-30-used-Kindle-iot-internetofthings-eink-epaper-lankybutmacho/[4]https://wwwdit/r/Kindle/comments/l75hjz/your_next_smart_home_device_is_a_30_used_Kindle/[5]https://github/lankybutmacho/web-to-Kindle-heroku[6]https://kimmo/posts/7-building-eink-weather-display-for-our-home/[7]https://wwwstructables/Literary-Clock-Made-From-E-reader/
— 完 —
量子位 QbitAI · 头条号签约
关注我们,第一时间获知前沿科技动态
·通电后,如果连接了灯具,它会默认亮起,如当前状态。
·进入模式设置,先点击设置键,选择下方的模式,然后确认。默认情况下,灯是关闭的。此时,需要按下方向键将其选为开启状态。
·这里是时间设置。按OK键进入时间设置。我已经提前设置了时间。如果需要手动更改,请按上下键进行更改。设置完成后,按OK键跳到下一个要更改的选项。
·这是时间设置。我现在闪烁的是模式,即该时间段执行的模式。S01是默认全黑的。如果需要,可以在后面更改默认模式的亮度。设置完成后,按mode键返回初始界面。
·S03是月光模式,S02是100%全亮模式。我先将其调整为S02模式。
·后面还有很多模式,如果需要也可以添加。总共有8个模式。按一次mode键即可返回第一个模式。设置完成后,按mode键返回初始界面即可。因为现在是白天状态,录制时灯是全黑的。如果灯跟随自带的时间走,后续也会如此。
·如果现在是3:44,需要调整万年历或者时间,可以长按设置键,直到出现变化,再按一次即可调整。现在是日期设置和时间设置。每个选项设置完成后,按OK键即可切换。
·设置完成后,按mode键返回初始界面。取消后,长按mode键回到最初的界面。然后保持该界面不动,时间到了灯会自动执行。
·要修改默认配置的亮度,可以长按mode键,S01默认全黑,可以在此处调整CH1、CH2、CH3和CH4的亮度。我们只连接了CH1,因此只需要调整CH1的亮度。
·现在这个时间段是黑色的。调整后,如果亮度为10%,退出后灯会显示10%的亮度。调整完成后,将亮度调整为默认设置。其他模式的设置也按照相同的操作方式进行。
詹士 发自 凹非寺
量子位 | 公众号 QbitAI
除了吃灰,Kindle还能干什么?
不是泡面盖,而是你的智能管家,每天出门前,提醒你天气情况、即将到达的包裹。
这玩意有人已经造出来了。
一位做前端与设计的美国小哥,将一块10多年前的老Kindle改造成了一块能显示日历、天气、网购包裹、家务提醒的智能显示板。
整个过程中,无需再买任何硬件,操作流程也简单。
在reddit上,该项目已获得500+个赞,有网友表示自己已改造了好几块了。
具体如何操作的?
往下看。
成本比树莓派还便宜之所以上手改造,始于小哥希望在手机之外能有个显示工具挂墙上,随时提醒自己时间日程、天气、快递哪天到……等等信息。
考虑到Kindle价格比树莓派还便宜,基于Linux操作系统,易破解调试,且墨水屏比发光屏幕更自然地融入家中环境,他果断从网上花30美元购买了一台二手Kindle4,约合211.5人民币。
但仍有三个问题要解决:
Kindle会自动进入睡眠状态并显示屏保程序;
如果想更新屏幕数据,每次浏览器页面都会重新加载,观感很差;
Kindle浏览器还有一些难看又冗余的元素,比如标题、URL栏,且并不好看;
基于上述原因,小哥设计了一套解决思路:
部署一个能获取网页屏幕截图的服务器,让Kindle作为终端显示屏,每分钟下载一次该截图。
鉴于市面上已有部分平台提供定时截屏服务,但收费不低,小哥决定自己编写一个小型服务器,使用 Puppeteer截图,再依靠ImageMagick转换格式。
带着这一规划,他开动了。
先是设置图像服务器。
小哥自己编写了代码并在Heroku创建一个免费账户,在平台填好项目名,就能一键部署。(现已开源,人人可用,链接见文末)
退出前,别忘了记下URL。
接着,回到Kindle本体。
连上WiFi,对其进行越狱,网上相关教程有很多,跟着步骤走就行,注意下载文件及流程与版本号相符就行。(相关资料已附在参考链接)
然后,安装USBNetwork插件。复制.bin文件进去就行,接着通过Settings设置->更新Kindle,完成安装。
断开Kindle与电脑的连接,通过设备键盘,输入;debugOn
回车,启动调试模式。
继续打开键盘,输入~usbNetwork,回车,等待几秒,再输入;debugOff,回车。
重新连接电脑。在桌面打开命令行,输入ssh root@192.168.15.244并回车。然后输入默认密码——mario。
现在,你已经可对Kindle进行编程了。
接着,调整驱动从「只读」变成「可写」状态,输入mntroot rw并回车。
再输入下方代码,创建图像下载脚本,让你能打开并编辑。
nano /mnt/us/script.sh
在编辑器中输入下面代码,注意「Insert_your_URL_from_step_2_here」部分,替换为前面第二步复制的URL:
curl Insert_your_URL_from_step_2_here -o status.pngeips -ceips -ceips -g status.png
上述代码中,第一行是保存图像到status.png文件,两个eips-c命令是为了清除屏幕,最后一行为显示图像。
完成后,输入control-O,再输入control-X,保存并退出编辑器。
然后运行脚本测试一下,输入/script.sh,就能看见屏幕上能看见图像显示。
最后一步, 设置定时程序,让其每分钟刷新。
由于Kindle系统与其他Linux设备一样,其中有个cron工具,可按计划定时运行。
只需打开配置文件:
nano /etc/crontab/root
将下面命令添加到底部:
*****/mnt/us/script.sh
同样,输入⌃O,回车,再输入⌃X,最后重启:
/etc/init.d/cron restart
BINGO!搞定!
很多人都在魔改墨水屏上述魔改的小哥名叫Matt Healy,是一位设计师兼前端工程师。
他目前也是一家SaaS平台的联合创始人,主要为其他企业提供用户/客户喜好研究与需求洞察服务,闲暇时间,他还做了个自己的主页。
不止他一人,其实改造墨水屏设备的玩家还有不少。
比如一位芬兰程序员Kimmo做了个墨水屏天气显示器,每天出门前提醒自己穿什么衣服合适。
这两天,他的改造帖子冲上了HackerNews前3。
更早时候,还有一位荷兰小哥,女票是英国文学老师,他用Kindle做了个文学时钟送给了对方。
当程序启动后,Kindle将会以文学名著段落显示当前时间,此外,还能猜测该句来自哪本书。按下翻书按钮,屏幕就会显示答案,深得女票喜爱。
最后问问, 你觉得Kindle还能用来干什么?
参考链接:[1]https://matthealy/Kindle[2]https://wikileread/wiki/Kindle_Hacks_Information#Jail_break_JB[3]https://blog.adafruit/2021/01/29/your-next-smart-home-device-is-a-30-used-Kindle-iot-internetofthings-eink-epaper-lankybutmacho/[4]https://wwwdit/r/Kindle/comments/l75hjz/your_next_smart_home_device_is_a_30_used_Kindle/[5]https://github/lankybutmacho/web-to-Kindle-heroku[6]https://kimmo/posts/7-building-eink-weather-display-for-our-home/[7]https://wwwstructables/Literary-Clock-Made-From-E-reader/
— 完 —
量子位 QbitAI · 头条号签约
关注我们,第一时间获知前沿科技动态
上节分享了单片机定时/计数器实现数码管动态刷新的程序代码,本节利用定时/计数器以及外部中断实现一简单的电子时钟功能。对应的视频课程为:单片机应用实践篇之定时/计数器实现按键可调电子时钟,视频链接:/d/file/gt/2023-09/pikkguz1fxz 四位数码管显示 分钟:秒(可根据需要调整显示界面) KEY1 外部中断0 状态切换KEY2 外部中断1 参数调整产生时间基准 定时器0 数码管动态刷新 定时器1*************************************************************/#include <reg51.h>#include "display.h"#include "time.h"#include "exit.h"void showNormal();void showSec();void showMin();void showHour();//状态变量unsigned char state = 0;void main(){EX0_Init();EX1_Init();Timer1Init();Timer0Init();EA = 1;while(1){switch(state){case 0:TR0 = 1;showNormal();break;//正常时钟状态case 1:showSec();break;//调秒case 2:showMin();break;//调分case 3:showHour();break;//调时default:break;}}}//正常时钟显示界面void showNormal(){LEDBuf[0] = min/10;LEDBuf[1] = min%10;LEDBuf[2] = sec/10;LEDBuf[3] = sec%10;}//调秒显示界面void showSec(){LEDBuf[0] = 23;//关LEDBuf[1] = 23;//关LEDBuf[2] = sec/10;LEDBuf[3] = sec%10;}//调分显示界面void showMin(){LEDBuf[0] = min/10;LEDBuf[1] = min%10;LEDBuf[2] = 23;//关LEDBuf[3] = 23;//关}//调时显示界面void showHour(){LEDBuf[0] = hour/10;LEDBuf[1] = hour%10;LEDBuf[2] = 23;//关LEDBuf[3] = 23;//关}
//time.c#include "time.h"#include "display.h"//全局变量定义unsigned char timerCnt;unsigned char sec;unsigned char min;unsigned char hour;void Timer0Init(void)//50毫秒@12.000MHz{TMOD &= 0xF0;//设置定时器模式TMOD |= 0x01;//设置定时器模式TL0 = 0xB0;//设置定时初值TH0 = 0x3C;//设置定时初值TF0 = 0;//清除TF0标志ET0 = 1;}void Timer1Init(void)//1毫秒@12.000MHz{TMOD &= 0x0F;//设置定时器模式TMOD |= 0x10;//设置定时器模式TL1 = 0x18;//设置定时初值TH1 = 0xFC;//设置定时初值TF1 = 0;//清除TF1标志ET1 = 1;TR1 = 1;//定时器1开始计时}/*************************************1、中断服务函数一定是一个没有返回值的函数2、中断服务函数一定是没有参数的函数3、中断服务函数函数名后跟关键字 interrupt 4、interrupt n 0 - 4 5个中断源 8*n + 0003H 0003H INT0 000BH T0 0013H INT1 001BH T1 0023H ES5、中断服务函数不能被主程序或其他程序所调用6、 n 后面 跟 using m (0 - 3 )工作寄存器组***************************************/void timer0_ISR(void) interrupt 1{timerCnt++;if(timerCnt >= 20)//20次50ms中断,即1S时间到{timerCnt = 0;sec++;if(sec >= 60){sec = 0;min++;if(min >= 60){min = 0;hour++;if(hour >= 24){hour = 0;}}}}TL0 = 0xB0;//设置定时初值TH0 = 0x3C;//设置定时初值}void timer1_ISR(void) interrupt 3{TR1 = 0;Display();TL1 = 0x18;//设置定时初值TH1 = 0xFC;//设置定时初值TR1 = 1;}
//time.h#ifndef __TIME_H__#define __TIME_H__#include <reg51.h>extern unsigned char sec;extern unsigned char min;extern unsigned char hour;void Timer0Init(void);void Timer1Init(void);#endif
//exti.c#include "exit.h"#include "time.h"//外部变量声明extern unsigned char state;void EX0_Init(){IT0 = 1;EX0 = 1;}void EX1_Init(){IT1 = 1;EX1 = 1;}void EX0_ISR() interrupt 0{TR0 = 0;state++;if(state >3 )state = 0;}void EX1_ISR() interrupt 2{switch(state){case 0:break;case 1:sec++;if(sec >= 60) sec = 0;break;case 2:min++;if(min >= 60) min = 0;break;case 3:hour++;if(hour >= 24) hour = 0;break;default:break;}}
//exti.h#ifndef __EXIT_H__#define __EXIT_H__#include <reg51.h>void EX0_Init();void EX1_Init();#endif
//display.c#include "display.h"unsigned char code leddata[]={ //数码管的段码表 0x3F, //"0" 0x06, //"1" 0x5B, //"2" 0x4F, //"3" 0x66, //"4" 0x6D, //"5" 0x7D, //"6" 0x07, //"7" 0x7F, //"8" 0x6F, //"9" 0x77, //"A" 0x7C, //"B" 0x39, //"C" 0x5E, //"D" 0x79, //"E" 0x71, //"F" 0x76, //"H" 0x38, //"L" 0x37, //"n" 0x3E, //"u" 0x73, //"P" 0x5C, //"o" 0x40, //"-" 0x00, //熄灭 };unsigned char LEDBuf[] = {22,22,22,22};//数据显示缓冲区unsigned char code PLACE_CODE[] = {0xfe,0xfd,0xfb,0xf7};//位选信号void Display(){static unsigned char i = 0;//1、送段码//2、送位选//3、延时 //4、消隐switch(i){case 0:GPIO_DIG = 0x00;GPIO_DIG = leddata[LEDBuf[0]]; GPIO_PLACE = PLACE_CODE[0];i++;break;case 1:GPIO_DIG = 0x00;GPIO_DIG = leddata[LEDBuf[1]]; GPIO_PLACE = PLACE_CODE[1];i++;break;case 2:GPIO_DIG = 0x00;GPIO_DIG = leddata[LEDBuf[2]]; GPIO_PLACE = PLACE_CODE[2];i++;break;case 3:GPIO_DIG = 0x00;GPIO_DIG = leddata[LEDBuf[3]]; GPIO_PLACE = PLACE_CODE[3];i = 0;break;default:break;}}
//display.h#ifndef __DISPLAY_H__#define __DISPLAY_H__#include <reg51.h>//IO的声明#define GPIO_DIG P0 //段码 IO#define GPIO_PLACE P2 //位选 IO#define N 4 //数码管个数unsigned char code leddata[];extern unsigned char LEDBuf[];void Display();#endif
执行代码后,通过Proteus仿真的显示界面如下:
正常时钟显示界面(分钟:秒)
调秒显示界面
调分显示界面
调时显示界面
程序代码仅供初学的同学参考学习,代码可以根据自己的风格进行相应的优化处理,仅供参考。