×

开源硬件之向所有有礼貌的司机表示感谢

消耗积分:0 | 格式:zip | 大小:0.30 MB | 2022-12-21

张生

分享资料个

描述

只要我一直在开车,我就希望能够以更有意义的方式与我周围的随机司机进行交流。在我看来,闪光、挥手、比挥手更重要的手势、按喇叭或猛踩刹车最终都成为一种非常粗糙的交流机制。

其灵感来自詹姆斯·邦德的电影,在影片的开场场景中,他在奥斯汀·马丁的后窗上展示了一些文字。我想,我真的可以告诉(不仅仅是用波浪形的手表达)另一辆车里的司机我在想什么。

 

还有一个准真人演示:

 
pYYBAGOiaEmAcUHPAAewbtAc6pw735.jpg
 

这是概念草图:

poYBAGOiaGOAGfrGAAOnszDdHhY298.jpg
这个概念
 

这个项目有一个额外的挑战,因为 MKR1000 是一个预发布板,没有正式的文档。

所以在项目的第一步: 

让 MKR1000 说话

我很幸运能够进入由http://arduino.cc赞助的论坛,该论坛为我们每个发行版的所有者提供了一个私人论坛。在一个充实的星期六之后,我设法能够对电路板进行编程并让所有组件正常工作。

我当前的设置涉及 Arduino IDE 版本 1.6.9 每小时构建一次。如果你像我一样,那么在项目中使用“每小时”构建至少会让你“不舒服”。  

安装 IDE 后,我使用 IDE 的板管理器下载板的驱动程序。我还使用 IDE 库管理器加载了以下库:Adafruit DotStar、Adafruit DotStarMatrix、Adafruit GFX、ArduinoJson 和适用于 Arduino 的 Windows Virtual Shields。

当这块板子正式发布时,流程会简单很多。所以,我不打算在这里详细介绍。在文章末尾有一个项目参考可以帮助您做到这一点。

构建电子设备的第一条规则:永远不要让魔法冒出电路!

MKR100 是一款基于 3v3 的开发板。没有我想要的所有文档,我不知道它们是否能承受 5 伏电压。不仅一些组件确实需要 5 伏电压来建立正确的逻辑 1 和 0。

这带来了 Adafruit 对 4 通道双向电平转换的需求。蓝牙卡和特别是 DotStar 矩阵都非常像一个完整的 5 伏特。所以,连接这些东西时要小心。

确保组件正常工作

在我担心让所有东西一起工作之前,我想确保所有组件都能正常工作。

我从 Adafruit 8x32 DotStar 矩阵开始。我发现我的人际关系有点古怪。为了使这不是问题,我使用了一些我放在周围的插头引脚并将它们焊接起来。  

pYYBAGOiaKeARBJeAAhyIopEgs4376.jpg
即将焊接头针
 

牢固连接收割台销。我将数据和时钟输入路由到 MKR1000 上标有 SDA 和 SCL 的 SPI 引脚。  

牢固连接收割台销。我将数据和时钟输入路由到 MKR1000 上标有 SDA 和 SCL 的 SPI 引脚。  

我将示例草图“文件 > 示例 > Adafruit DotStarMatric > matrixtest”加载到 IDE 中。调整代码中的DATAPIN为11,CLOCKPIN为12。构建并部署了解决方案。在对矩阵进行了一些选择之后,我得到了一个可以工作的显示器。

 

接下来是让 Virtual Shield 通过蓝牙适配器工作。这真的很简单。我按照 github 存储库 https://github.com/ms-iot/virtual-shields-arduino中提到的说明进行操作我唯一需要做的改变是 TX 和 RX 引脚。这些是我板上标记的引脚 14 和 13。  

我会注意到,在以前的版本中,我必须断开 TX/RX 引脚才能上传新草图。我很高兴地报告,情况已不再如此。

遍历代码

现在一切正常,我将花点时间浏览一下这个项目的特定代码。

为了访问所有功能,您需要包括以下内容:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

前 5 个包含应该很清楚。  

VirtualShield.h 包含通过蓝牙适配器进行通信的基本功能。无论您想访问哪个传感器,这都是必需的。

Text.h 文件获取更好的文本,即字符串处理。

Graphics.h、Recognition.h 和 Colors.h 包含访问虚拟屏幕和启用语音识别所需的功能。虽然,这个挑战还没有完成,但我会在未来编写语音功能。

接下来是重要代码行列表,初始化 DotStar 矩阵和初始化 Shield 对象:

Adafruit_DotStarMatrix matrix = Adafruit_DotStarMatrix(
  32, 8, DATAPIN, CLOCKPIN,
  DS_MATRIX_TOP     + DS_MATRIX_LEFT +
  DS_MATRIX_COLUMNS + DS_MATRIX_ZIGZAG,
  DOTSTAR_GBR);

const uint16_t colors[] = {
  matrix.Color(255, 0, 0), matrix.Color(0, 255, 0), matrix.Color(0, 0, 255),
  matrix.Color(255, 0, 255), matrix.Color(255, 0, 106), matrix.Color( 255, 255, 255) };

VirtualShield shield;
Graphics screen = Graphics(shield);
Recognition speech = Recognition(shield);

第一行告诉 DotStar 库矩阵的大小和布局。有关各种选项,请参阅 matrixtest 示例或 Adafruit_DotStarMatrix.h 文件。

这些颜色适用于 DotStar 库。

最后 3 行启动屏蔽并初始化对象,以便与手机中的传感器一起工作。

接下来像所有 Arduino 草图一样,我们需要处理 setup() 方法

void setup() {
  matrix.begin();
  matrix.setTextWrap(false);
  matrix.setBrightness(40);
  matrix.setTextColor(colors[0]);

  DisplayText("Initializing...", 4, 10);

    // set up virtual shield events: 
    shield.setOnRefresh(refresh);
    speech.setOnEvent(onSpeech);
    screen.setOnEvent(screenEvent);   

    // begin the shield communication (also calls refresh()).
    shield.begin(); //assumes 115200 Bluetooth baudrate


  DisplayText("Initializing...finished", 3, 10);
}

“矩阵”行是不言自明的,执行这些行后,我现在可以向矩阵发送一些信息性消息。

“屏蔽”行现在设置回调方法。当事件发生时,将根据需要调用这些方法。  

现在是整个草图最复杂的方法

void loop() {
  // checkSensors() checks for return events and handles them (calling callbacks). This is VirtualShield's single loop() method.
  shield.checkSensors();
}

是的,你明白了。我们不断检查传感器是否已触发以及需要处理的事件。

现在好了,让我们真正处理一些事件。首先是 refresh() 方法。当许多不同的事件发生时,它将被调用。我们目前关心的一个事件是蓝牙何时连接。我们需要事件,以便我们可以重绘屏幕,使其看起来像它应该的那样。 

void refresh(ShieldEvent* shieldEvent)
{
  // put your refresh code here
  // this runs whenever Bluetooth connects, whenever the shield.begin() executes, or the 'refresh' button is pressed in the app:
  screen.clear(ARGB(123,86,204));
  screen.drawAt(0,0, "");

  thanksId      = screen.addButton(10, 50,   ". Thank you .");
  welcomeId     = screen.addButton(10, 100,  ".  Welcome  .");
  turnLeftId    = screen.addButton(10, 150,  ".      Left       .");
  stoppingId    = screen.addButton(175, 50,  ". Stopping  .");
  startingId    = screen.addButton(175, 100, ".   Starting  .");
  turnRightId   = screen.addButton(175, 150, ".    Right     .");
  backoffId     = screen.addButton(10, 225,  ".              Back Off                 .");
  calling911Id  = screen.addButton(10, 290,  ".           Calling 911                .");
}

此方法使用浅紫色背景清除屏幕,然后继续将各种按钮放在屏幕上。注意单词周围的间距。这是虚拟盾牌功能的当前限制,因为我真的很想将事物居中以使其看起来不错。

那么当我触摸其中一个按钮时会发生什么?一个事件被触发,并在下面的代码中处理。

void screenEvent(ShieldEvent* shieldEvent) 
{
  if(screen.isPressed(thanksId))
  {
    DisplayText("Thank You", 5, 100);
  }

  if(screen.isPressed(welcomeId))
  {
    DisplayText("You're welcome", 2, 100);
  }
  if(screen.isPressed(backoffId))
  {
    DisplayText("Please back off", 4, 100);
  }
  if(screen.isPressed(stoppingId))
  {
    DisplayText("...stopping...", 0, 100);
  }
  if(screen.isPressed(startingId))
  {
    DisplayText("...starting...", 1, 100);
  }
  if(screen.isPressed(turnLeftId))
  {
    DisplayText("Turning LEFT", 3, 100);
  }
  if(screen.isPressed(turnRightId))
  {
    DisplayText("Turning RIGHT", 3, 100);
  }
  if(screen.isPressed(calling911Id))
  {
    DisplayText("Calling 911", 0, 100);
  }
}

一个事件到来,代码检查哪个按钮被按下,我们调用 DisplayText 方法来显示内容。

最后,文本如何进入矩阵?DisplayText 方法将为您处理。

void DisplayText(String message, int colorIndex, int currDelay)
{
  int x = matrix.width(); 
  int maxX = -1 * (message.length() * 5 + message.length());
  matrix.setTextColor(colors[colorIndex]);

  while( x > maxX) {
    matrix.fillScreen(0);
    matrix.setCursor(x, 0);
    matrix.print(message);

    --x;

    matrix.show();
    delay(currDelay);
  }
}

这个方法计算出这个字符串到底有多宽。我们需要知道,这样我们才能确保字符串完全滚动进出视图。字母之间的间距为 5 宽 + 1。

建造围栏

构建非常简单。我找到了一个比矩阵足迹大的大小合适的盒子。拿了一块 1/4" 的波罗的海桦木,它比我需要的大,然后把它切成合适的尺寸。  

专业提示:不要尝试测量这个。只需将盒子放在台锯上,然后将栅栏推紧即可。
 
 
 
poYBAGOiaL6Ab7e9AAV44iqLbkA986.jpg
 
1 / 2
 
专业提示:在台锯上切割任何种类的原料时,请将锯片高度调整到最低限度。它最大限度地减少了木材上的燃烧,并降低了所有额外刀片旋转的风险。
poYBAGOiaNaAZ-whAARfHTAQtNk846.jpg
 

使用与台锯相同的技术。首先将矩阵放在胶合板上。定位好后,再标出接线的水平中心和垂直中心(包括辅助电源接线)。您现在需要做的就是连接线以找到您将要钻孔的孔的中心。

是的,我说的是“钻孔”,而不是“钻孔”。上次我在塑料上“钻”孔时,得到了一些非常不令人满意的结果。这次我使用 了 Forestner 钻头我在下面有一张他们的照片。注意边缘是用来切割的,中间有一个刮刀用来挖出不需要的木头。做一个更好的“洞”。现在,开始“钻孔”,您可能想继续钻悬挂孔。

拿一张 120 号砂纸,轻轻打磨整块砂纸。确保“缓解”电路板的边缘包括刚刚制作的所有孔。一定要把板子擦干净,这样板上就没有其他“东西”的锯屑了。

现在是时候处理塑料盒了。  

在盒子的两端钻两个孔。这些用于电源连接器和与矩阵的连接。暂时不要钻矩阵辅助电源孔。

现在,在盒子背面贴几条双面胶带,然后将盒子贴在胶合板上。因为这是“可重新定位”的胶带,我真的希望它能永远粘住。我在上面放了一些沉重的书,并放置了 24 小时。为什么是24小时?磁带说明说不要。这对我来说是一个足够好的理由。

最后一个洞的时间。您现在应该有辅助电源连接孔的准确位置。把它弄出来,享受你“精确”的工作。 

 
 
 
poYBAGOiaPmAZRLVAAesmxFDlkc792.jpg
 
1 / 6
 

把智慧放在盒子里

似乎面包板的尺寸正好适合盒子,但我希望能够从 MKR1000 插入/拔出 USB 连接器。所以,我不得不让面包板更短。

 
 
 
pYYBAGOiaSqAE_MTAAk64VJyPVE690.jpg
 
1 / 4
 

好的,在那次创伤之后,剥下面包板的背面并将其粘住。确保避开辅助电源连接孔。

 
 
 
poYBAGOiaVKAeq4SAAb-bkyFCHI763.jpg
 
1 / 3
 

将矩阵连接到胶合板的正面,将连接穿过孔。用一些热胶固定矩阵。

让我们谈谈权力

即使我将亮度设置为 40%,如果我点亮所有 256 个像素,最大电流大约为 7.5 安培。远远超过 MKR1000 所能提供的。对我来说幸运的是,没有一个显示是静态的,我没有在整个矩阵附近的任何地方点亮。辅助电源连接来救援。我提供高达 4A 的电流。我想既然它不是持续的也不是静态的,电源应该是好的。 

我还有一个备用的壁式电源适配器,当它在车内通电时,我使用它的末端为 MKR1000 供电。

 
 
 
pYYBAGOiaXKAVv9gAAYu1Haoqq8189.jpg
 
1 / 2
 

我正在考虑在项目中构建一个电源转换器,以获取 12V 汽车电源并将 5V 提供给项目。经过深思熟虑,以 5.00 美元的价格购买一个 5V 4A 交流适配器并使用我已有的交流转换器在所有方面都更好。当涉及到这些东西时,简单通常更好。

挂牌子

我曾计划使用“球弹力绳”和一些吸盘将其固定在后挡风玻璃上。这么说吧,我在该地区还有更多工作要做。

 
 
 
pYYBAGOiaZWAatUHAAYcFqepDnw366.jpg
 
1 / 2
 

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !