0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

油箱油位监控仪的制作

454398 来源:工程师吴畏 2019-08-21 09:03 次阅读

第1步:需要的零件,耗材和工具

油箱油位监控仪的制作

电子产品

粒子光子

US-100超声波测距仪

Adafruit的Verter降压/升压转换器

低压差可调电压调节器:MIC29302WT; 1.25-26V; 3A

6V 4.5Ah密封铅酸电池“凝胶电池”

2 Maxim Integrated DS18B20数字温度传感器

2太阳能电池板,每个5V 500mA 2.5W

外部WiFi天线(从旧笔记本电脑中清除)

1欧姆10W电阻(扫气)

瞬间开关(清除)

3 10k Trim电位器(扫气)

保护二极管(扫气)

短microUSB电缆(扫气)

工具和用品:

焊台

剥线钳

万用表

台式电源

热缩管和热风棒

热胶枪

手钻或Dremel工具

原型Photon Shield PCB(在Maker Faire免于Bluz)这是Adafruit的一个不错的选择。)

PVC管和锯切割到你的ta的高度nk

包含电子设备的聚丙烯塑料食品储存盒

连接线

金属支架

用于固定系统的带子,但可以拆下调试

太阳能电池板支架(扫描电脑显示器支架)

透明5分钟环氧树脂

PC-7环氧树脂浆 - 非常坚固和厚实!

丁腈手套

硅橡胶胶

可选:用于调试传感器通信示波器

步骤2:超声波测距仪 - US-100 Wins!

这种坦克级别监控方法的操作理论非常好直截了当:从流体表面反射声音脉冲,并通过测量回声的延迟,计算水平在水箱中的下降程度。在实践中,它根本不是直截了当的。值得庆幸的是,有很多便宜的超声波测距仪用于爱好机器人,可以做得很好。我最初使用的是HC-SR04。该器件输出一个长度与距离相对应的TTL脉冲,Arduino(或者我的情况下,Photon)必须精确测量其长度。事实证明这非常棘手并且充满了噪音问题。它的准确性很差(重复性结果差异大约2厘米),精度差(使用NewPing库最好可能是1厘米),可靠性差(有些数据完全错误)。

感谢Andreas Spiess,我发现了US-100超声波测距仪,其发现频率低于€并具有数字模式,以毫米为单位响应目标距离(不是厘米,与其他数字相同)超声波测距仪)。与大多数模拟超声波测距仪不同,它在内部进行从回波延迟到距离的转换,而不是Arduino。我发现HC-SR04在它和Photon之间的线路上容易受到噪声的影响。数字信号不易出现噪声问题。 US-100还包括一个温度传感器,用于校正声速随温度的变化。另一个好处是它可以在3.3V下使用,不像大多数需要5V工作良好的超声波测距仪。为了让它能够存活在像这样的全天候应用的元件中,我焊接连接线并用5分钟的环氧树脂封装电路板。图为我的坦克通风帽,传感器用热胶固定。煤油(加热油)几乎不像汽油一样易挥发或易燃,因此这类装置几乎没有爆炸危险。 (显然,如果你测量的是更易燃的液体,你需要小心地将任何电子设备与蒸汽隔离开来)

香蕉机器人以5美元的价格销售US-100,并且在数字(串行数据)和模拟(脉冲宽度)模式下可以找到最佳描述,您可以通过跳线选择它。如果您在本Instructable的末尾扫描我的代码,您将看到只需要通过Photon的TX线向US-100发送一个命令(0x55或0x50)来查询传感器,它将在几毫秒内通过RX回复以mm为单位的距离或以摄氏度为单位的温度。

第3步:错误的回声问题 - 错误修复!

正如你在照片中看到的那样,我的坦克有很多内部结构形状,这给我带来了许多问题,这些错误的回声并非来自油面。即使锅炉正在燃烧燃油,油耗也会在某些时候停止。在油位下降,暴露内部油箱结构之前,不会发现虚假回波问题。我成功地将超声波束与10cm的热缩管聚焦在发送和接收传感器上(见图)。但是这种方法对我如何将盖子放回油箱非常敏感。比起小型热缩管好,我想出了一个想法,事实证明,这个想法很久以前就被发明了,被称为“静止管”。我的是PVC管,从罐的最底部延伸到顶部,超声波应答器放置在其顶端内。在其底端有两个凹口,允许油从下方轻松地从管道中流入和流出管道,因此管道内的水平始终与水箱的其余部分相同。它被称为静止管,因为即使在填充过程中,内部的水平也会相对平坦和平静。 (这在校准期间很重要。)并且因为管道的内表面非常光滑,所以不需要担心错误的回声。 除了earwigs!我很少随机获得奇怪的读数。当我拿下帽子进行调查时,我看到大约5个蠕虫漏掉了,一个人朝着PVC管道走去!我认为我的数据中的错误不是由于我的代码中的错误,而是我的坦克中的实际错误,这很滑稽!现在,我已经用丁腈手套和一些硅橡胶更加安全地关闭了通风帽,以“调试”它,并阻止了穗和蜘蛛在那里开店。它不是一个完美的密封,允许坦克中的空气膨胀和收缩。

步骤4:粒子光子是和不是Arduino

IoT项目需要一个带Wifi的微处理器。我选择了粒子光子,因为这是Ventz用于他的坦克监视器的。

如果我现在开始这个项目,我可能会使用Arduino.cc提供的一个支持WiFi的Arduinos,例如Arduino MKR WiFi 1010。我对粒子光子并不满意,但他们基本上创建了自己的并行Arduino类宇宙,而不仅仅是让他们的产品可以与Arduino IDE一起使用。他们的Web IDE非常类似于Arduino IDE,但您可能想要使用的每个库都必须由他们导入和验证才能轻松地将其添加到草图中。像通过USB重新编程Photon或甚至使用串行监视器进行调试一样简单,因为它需要安装软件层(Homebrew,dfu-util,NPM,Xcode等)并学习命令行接口(CLI)。他们希望您通过无线方式重新编程(OTA),但这并不总是可行的,因为设备在大多数时间处于脱机状态并且处于休眠状态。由于MacOS X High Sierra的过度安全性变化,很难安装Particle的CLI。尽管Particle的在线文档通常非常好,但导航和查找内容却过于复杂。我通常只是放弃并使用谷歌搜索。从好的方面来说,Particle的客户服务优秀,并且问题会在一天或更短的时间内得到技术支持的详细回复。另一种选择是使用ESP32,它现在似乎在Arduino IDE中具有相当不错的功能,并且整体功耗更低。

Photon是一款3.3V器件,由microUSB(5V)或3.6供电其Vin引脚为-5.5V。它的数字输入均为5V耐压(“FT”),但其模拟引脚不是。确保不要对它们施加超过3.3V的电压。

步骤5:电池:密封的铅酸凝胶电池

我第一次尝试使用LiPo电池,但很快发现当温度低于冰点时,它几乎毫无价值。这就是为什么电动汽车需要电池加热器才能在冬季获得合理的范围。据我所知,在寒冷的冬天早晨开始使用老式汽油/汽油车时,铅酸电池在寒冷中运作良好。通过在冰冻条件下充电,可以迅速破坏LiPo。

我使用的电子设备在激活时吸收大约80 mA,可能用于WiFi连接的很多。

所以从理论上说,这个电池应该可以为系统供电几天没有太阳。由于爱尔兰可能有超过几天的阴天,我通常会在每次循环结束时让我的Photon睡5-10分钟,如下所示:

System.sleep(WAKEPIN, RISING, SleepSecs);

WAKEPIN连接到瞬时开关(将线路从0上拉至3.3V),我可以使用它来帮助重新编程Photon,而无需打开盒子,如果它正在睡觉。我还在循环中添加了大约10秒的延迟,因此如果我正确计时,我可以通过WiFi重新闪烁Photon OTA(无线),然后再进入睡眠状态。

这些铅酸电池是“密封的”,但有一个通风口,当快速充电时会散发出易燃的氢气,因此最好确保外壳上有某种防雨通风口。

第6步:Oilwatcher原理图

这里我已经勾画了整个项目的接线图。它经历了许多版本和升级,都散落在我的制造商笔记本电脑中。所以我把它拿下来,打开盒子,然后回溯现在的一切。它并不完美,但它有效!。..有关设置装饰罐的信息,请参阅校准步骤。

我欢迎您提出改进建议和想法。如果您为自己制作版本,请在评论中告诉我们,或者更好,编写自己的Instructable!

步骤7:太阳能和安装

我通过低压差可调电压调节器焊接两个串联的太阳能电池板,为“6V”铅酸电池充电(MIC29302)。这些面板的额定电压为5V 500mA 2.5W,每个面板为13 x 15cm。它们绝对没有电路,只有太阳能电池,所以我将可调电压调节器设置为7.3V,电池前面说的是一个很好的充电电压。我发现太阳能电池板在昏暗的灯光下成为放电的好方法。我发明了太阳能电池板除霜系统!所以我将一个二极管串联起来,以确保电流仅从它们流入电池而不是电池。确保它是一个坚固的二极管,因为充电电流可能高达1A。务必使用环氧树脂或硅橡胶防风雨,以免腐蚀。与我的老鼠窝不同,将所有暴露的PCB引线,焊料,电线等绝缘,以防止释放出使其全部工作的神奇烟雾。对于我的外部DS18B20温度传感器,我选择了更昂贵的防水版本。

为了给Photon供电,我将电池连接到Adafruit的Verter Buck/boost转换器。这可以采用各种直流电压(3-12VDC)并将其转换为Photon通过其微型USB端口所需的5VDC。因此,我的Oilwatcher一直在黑暗中工作,直到铅酸电池真的死了。与LiPo电池不同,铅酸凝胶电池不会因完全放电而损坏。

我在太阳能电池板上安装了几个金属支架和一些强力防风雨环氧树脂膏(PC-7)电脑显示器支架。我在Artificial Window Instructable项目中有几个看台。您应该仔细定位并指向您的太阳能电池板,以避免阴影和收集最多的阳光,特别是在较短的冬季。出于这个原因,我把它们瞄准在正午的太阳高度,在冬日,并有一个面板倾斜,以捕捉更多的早晨的阳光和一个更多的午后阳光。通过监控充电电流,您可以优化此功能。根据您的自由度,有些应用和网站也可以提供帮助。您应该牢固地安装面板以抵御风和其他外部危险。我的是一个4x4的木柱子,用来挡住我们坦克周围的栅栏。

步骤8:校准:体积和电压

油箱mm到L校准

制作一个有用的设备来测量你剩下多少升(或加仑)在您的坦克中,您需要将测距仪的信号(毫米(或厘米))转换为升。如果坦克是垂直圆柱体或完美的矩形棱柱,这将是一个简单的问题,测量坦克的尺寸和做一些数学。但是如你所见,我的坦克是一个凸出的椭圆形,中间有两个空洞,各种山脊和诸如此类的东西。这向我表明,1厘米的回波距离变化将代表不同水平的不同数量的升。为了直接测量体积随油位变化的变化,我写了一个草图,以便在油箱加注过程中尽快收集数据(考虑到Particle Photon云服务的限制,大约每2秒钟)。我假设装满水箱的卡车有一个泵,它以恒定的流速泵送,驾驶员用大杠杆设置。卡车正在仔细计量交付的量(总共1000升)。我很惊讶地看到在填充过程中收集的应答器数据的附图中,曲线在整个范围内非常线性!也许坦克设计师调整了坦克中心的空隙,以补偿其中心增加的宽度。我将时间轴转换为升,并使用曲线的线性拟合测量转换因子:1.10 L/mm。我还注意到当油箱空了时转发器读数,这意味着当龙头吸入空气并且锅炉停止时。事实证明我的坦克是1304毫米。这对于设置有用的警报很重要;你需要知道锅炉什么时候退出,而不是在水箱干燥的时候。 (套管不够低,无法将油箱排干。)

电压和电流校准

我想要校准的另一件事是,预测如果连续阴天太多,电池何时会死亡,是整个系统吸收的电流和电池电压。为此,我使用1欧姆分流电阻与电池的(+)电源串联制作了一个粗略的“高端”双向电流传感器。我测量该电阻相对于地的每一侧(“抽头”)的电压。两个测量电压之间的差值,或该电阻上的电压降与通过它的电流成正比(欧姆定律,I = V/R)。当R = 1欧姆时,I = V,所以80mV是80mA。我将每个抽头电压除以一个已知量(约7/3因子,使7.2V降至~3.3V)和分压器(10k微调电位器,参见本Instructable后面的原理图),以防止超过3.3V最大值Photon的模拟输入。所以我使用了两个Photon的模拟输入线来测量这个电压降(另一个用来测量Vbatt)。为了校准这种设置,我使用具有良好电流读数的数字台式电源为整个设备供电,并在各种条件下获得电流测量:WiFi连接和光子激活(~90 mA)和休眠(~1-4mA)。因为1欧姆电阻上的电压降,特别是在分压器之后,实际上很小(并且光子的A/D线只有12位= 4096级),我需要平均100次测量以获得合理的无噪声当前值。这些可以很快收集。理想情况下,我应该制作一个差分放大器来增强电流信号,但这种简单的平均方法非常适合测量双向电流(充电和放电)。我尝试使用10欧姆分流器来增加信号,但光子无法通过它获得足够的汁液来工作。它陷入了掉电模式。我可以使用小于10k的微调电池来获得更好的抗噪性,但是会浪费电池加热微调电位器。 1k将是每个装配罐浪费7mA。

因此,模拟线路为我提供0-4095的数字单位,并且通过台式电源进行电流和电压测量,我能够将转换因子放入我的草图(见最后一步的代码)。显然,您需要自己校准设置以获得良好的数据。

我意识到我不需要使用单独的模拟输入线和自己的分压器来测量Vbatt,但我保留了因为它在概念上更清晰,并且因为电流监视器抽头必须对称地位于1欧姆电阻旁边。 (在添加电流测量系统之前,我已经在单独的电路板上安装了电压监控器。)

步骤9:使用Pushbullet发送警报

Pushbullet是一种跨平台的警报和消息服务。您的Photon草图将包含一些“警报”消息,这些消息将“发布”到粒子云,例如,当油位低于某个阈值时。在手机上安装Pushbullet应用程序,它将回显您希望所有其他设备发送的任何警报,通知和消息。因此,一旦你正确设置,就很难错过重要的“油低!”警告您的Oilwatcher设备将启动。

在pushbullet.com上注册一个帐户并阅读其API(应用程序编程接口)上的文档。您还可以阅读粒子控制台 - 集成部分的关键背景:https://docs.particle.io/guide/tools-and-features/。..

当您开始不堪重负时,请阅读Ventz Petkov的博客是关于如何设置的一步一步。

https://blog.vpetkov.net/2017/11/12/diy-monitor-heating-oil-tank-gallons-with-pushbullet-sms-and-email-alerting/

他还介绍了如何开始使用粒子光子。这个过程的很多截图都在他的Instructable中。他提到他转移到Pushover而不是Pushbullet,所以有一些选项可以确切地实现如何在手机上获取警报。

步骤10:使用ThingSpeak记录和共享您的数据

如果您只是想生活并忘记加热油,直到它耗尽,你可以跳过这一部分。

对于那些对我们在一年中不同时间使用多少油的科学和令人讨厌的细节感兴趣的人,或者发生了多少阳光或寒冷,ThingSpeak是给你的!太阳能电池板作为太阳传感器,以及我项目中包含的温度传感器,我正在慢慢建立一个合适的气象站! Thingspeak是一个收集和分析任何类型数据的地方,使用大量图表,如果您愿意,可以使用复杂的数学。它由The MathWorks创建,他也创建了Matlab,这是像我这样处理大数据的科学家的最爱。 “使用MATLAB分析的开放式物联网平台”是他们的标语。您可以将其全部保密,或与全世界分享您的数据,就像我在这里所做的那样。您可以让Photon草图每隔几秒在其云端的通道中将最多8个不同的变量写入“字段”。在ThingSpeak创建帐户后,创建一个频道作为收集和处理数据的地方。请注意其频道编号。使用字段名称设置频道并记下其字段编号。然后,您可以从API密钥选项卡中获取API密钥。在Oilwatcher草图设置中使用它:

unsigned long ThingSpeakChannelNumber = 123456;

const char * ThingSpeakWriteAPIKey = “THIS1ISAFAKEKEY45678”;

在主循环中,每当感兴趣的变量更新为新值时,调用ThingSpeak.setField(5, US100tempData); // Field 5 is for the US-100‘s onboard temperature sensor

ThingSpeak.setField(6, litres_of_oil); // Field 6 is for my Litres Remaining data

并接近每个循环的结束草图,您可以一次性发送所有数据字段:ThingSpeak.writeFields(ThingSpeakChannelNumber, ThingSpeakWriteAPIKey);

然后在您的频道的私人和/或公共视图选项卡中,创建数据的可视化(图表),每次新的一组时,它们都会自动更新数据由草图广播。

步骤11:Oilwatcher草图

附件是.ino文件,它是我的Oilwatcher代码AKA Photon的固件。 .zip文件还包含Rob Tillaart名为RunningMedian的库,尚未在Particle的Web IDE上使用。我在这里得到了该库的最新版本:

https://github.com/RobTillaart/Arduino/tree/master 。..

顶部包含的其他库位于Particle的库中,但不要忘记在项目中实际#包含以使代码正确编译。

如果你决定使用我所包含的所有铃声和口哨声,比如当前的监听,ThingSpeak等,你必须个性化的草图标题中会有一些常量。当然,必须仔细设置代码发出警报的油位。

快乐黑客

请在下面添加您的评论和问题。..

这是我的Oilwatcher草图(也包含在此步骤中):

/*

OilWatcherus100 sketch by Steve M. Potter steve.potter at gmail.com

To monitor heating oil tank level remotely, and send Pushbullet alerts when fuel is getting low.

Uses the Particle Photon board, Adafruit’s Verter voltage buck-boost converter, an additional adjustable voltage regulator, and PushBullet

Verter is available in EU from Pimoroni https://shop.pimoroni.com/products/verter-5v-usb-buck-boost-500ma-from-3v-5v-1000ma-from-5v-12v

Uses US-100 ultrasonic rangefinder.

Inspired by code and design by Ventz: https://blog.vpetkov.net/2017/11/12/diy-monitor-heating-oil-tank-gallons-with-pushbullet-sms-and-email-alerting/

and also from his Instructable: https://www.instructables.com/id/Monitor-Heating-Oil-Tank-Gallons-With-Email-SMS-an/

Last update 2018-10-03

Code is kept on http://build.particle.io called “OilWatcherUS100”

*/

// Libraries to include:

#include “RunningMedian.h” // by Rob.Tillaart at gmail.com

#include // for data logging and analysis, e.g. see https://thingspeak.com/channels/377827

#include // For the DS18B20 digital temperature sensors

#include // For the DS18B20 digital temperature sensors

//#include // Improved communication to the HC-SR04 ultrasonic rangefinder, by Tim Eckel

// Only for use in analog pulse mode.

// CONSTANTS:

#define VBATT A1 // blue wire. Monitors the voltage of the battery, through a 1/10 voltage divider.

#define POSCURPIN A4 // white Wire attached to one side of a 1-ohm shunt resistor in series with the battery, then a voltage divider.

#define NEGCURPIN A5 // blue Wire attached to the other side of a 1-ohm shunt resistor in series with the battery, then a voltage divider.

#define TEMPPIN D5 // yellow Onewire data line for temperature probe.

#define MAX_DISTANCE 1400 // Maximum distance we want to ping for (in mm)。

#define ONBOARDLED D7

#define WAKEPIN A2 // white wire, to wake from sleep with button.

#define SENSORS 2 // number of DS18B20 temperature sensors

// Variables:

TCPClient client; // for ThingSpeak

byte mac[6]; // the MAC address of the Photon

int battThreshold = 30; // Percent (from Dead to Full) below which a LOW BATTERY! warning is triggered (should be 》 2.5V)。

double FullChargeVolts = 6.5; // set for battery being used.

double DeadBattVolts = 5.5; // Lead Acid batt voltage that the system fails.

float voltage = 0.0; // Variable to keep track of battery voltage

double BattVolts = 0.0;

double battCalib = 2.16; //correction factor. TO RECALIBRATE THIS, measure batt at its terminals with o-scope.

double soc = 0.0; // Variable to keep track of battery‘s state-of-charge (SOC)

bool battalert = LOW; // Variable to keep track of whether battery alert has been triggered

double currentConversion = 2.27; //To convert A/D counts to mA of current in and out of the battery.

float BattCurrent = 0.0;

int negCurCounts;

int posCurCounts;

int negCurOffset = 0;

int posCurOffset = -27; // to calibrate the current-measuring lines, jumper the 1ohm resistor and make current zero.

int CurCountsDiff = 0;

int cm = 0; // Distance between sensor and oil surface. NewPing returns it in whole cm.

bool LowOilAlert = LOW; // Goes high when oil level gets below threshold (50mm presently)

int cm_of_oil = 200; // This is zero when it gets down to the spigot, not the bottom of the tank.

int mm_of_oil = 2000; //This is zero when it gets down to the spigot, not the bottom of the tank.

int litres_of_oil = 0;

int ZeroOilmm = 1304; // When my tank begins to suck air, the mm reading is this.

int difference = 0; // variable to hold temporary info during calculations

int q; // for loop counters.

int SleepSecs = 60; // seconds for device to sleep each loop.

unsigned long lastUpdate = 0;

float BoxCelsius = NAN;

float OutsideCelsius = NAN;

String BoxTempStr;

String OutsideTempStr;

DS18B20 TempSensors(TEMPPIN); //Sets name for calls to DS18B20 library, Pin D5 for 1-wire Temp Sensors.

retained uint8_t sensorAddresses[SENSORS][8]; // DS18B20 addresses retained across deep sleep in backup RAM as long as power is on VBAT or VIN of Photon

unsigned long ThingSpeakChannelNumber = ; //Enter your Channel number

const char * ThingSpeakWriteAPIKey = “”; // Enter your API key

// US-100 ultrasonic rangefinder:

unsigned int MSByteDistance = 0;

unsigned int LSByteDistance = 0;

unsigned int mmDistance = 0;

int Median_mm = 0; // Some of these I tried to use unsigned int and got an “ambiguous” compile error.

int TempmmDistance = 0;

int US100tempData = 0;

int junk;

unsigned long beginmillis = 0;

unsigned long nowmillis = 0;

unsigned long elapsedmillis = 0;

RunningMedian US100reading = RunningMedian(9);

// SETUP ______________________________________________________________________________________________

void setup() {

pinMode(ONBOARDLED, OUTPUT);

pinMode(VBATT, INPUT);

pinMode(POSCURPIN, INPUT);

pinMode(NEGCURPIN, INPUT);

pinMode(WAKEPIN, INPUT_PULLDOWN);

ThingSpeak.begin(client);

Particle.variable(“Box °C”, BoxTempStr); // temp sensor in box.

Particle.variable(“mm_of_oil”, mm_of_oil); // mm of oil remaining in tank (to spigot)。

Particle.variable(“L of Oil”, litres_of_oil); // litres of oil remaining in tank (to spigot)。

Particle.variable(“mmDistance”, mm_of_oil); // Average mm measured by rangefinder.

Particle.variable(“BattVolts”, BattVolts); // battery voltage.

Particle.variable(“BattPercent”, soc); // Li-ion battery State of Charge

Particle.variable(“Tank °C”, US100tempData); // Thermometer in ultrasonic sensor

Particle.variable(“Median_mm”, Median_mm); // Median mm measured by rangefinder.

Particle.variable(“Outside °C”, OutsideTempStr); // DS18B20 temperature outside.

Particle.variable(“Raw mm data”, TempmmDistance);

// To read the values from a browser, go to:

// http://api.particle.io/v1/devices/{DEVICE_ID}/{VARIABLE}?access_token={ACCESS_TOKEN}

STARTUP(WiFi.selectAntenna(ANT_EXTERNAL)); // selects the external antenna connector, not chip antenna.

Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.

Serial.println(“OilWatcher by Steve M. Potter. Last update 2018-10-03”);

Serial1.begin(9600, SERIAL_8N1); // for comm to/from the US-100 via RX and TX pins.

WiFi.macAddress(mac);

Serial.print(“MAC address of Photon: ”);

Serial.print(mac[0]&0x0f,HEX); // This may be in reverse order.

Serial.print(“:”);

Serial.print(mac[1]&0x0f,HEX);

Serial.print(“:”);

Serial.print(mac[2]&0x0f,HEX);

Serial.print(“:”);

Serial.print(mac[3]&0x0f,HEX);

Serial.print(“:”);

Serial.print(mac[4]&0x0f,HEX);

Serial.print(“:”);

Serial.println(mac[5]&0x0f,HEX);

TempSensors.resetsearch(); // initialise for DS18B20 temperature sensor search

for (int i = 0; i 《 SENSORS; i++)

{

TempSensors.search(sensorAddresses[i]); // try to read the 1-wire sensor addresses and if available, store them.

}

} // end setup()

// MAIN LOOP _________________________________________________________________________________________________

void loop() {

mmDistance = 0;

int DataToAvg = 9;

for (int avgloop = 1; avgloop 《 (DataToAvg + 1); avgloop++)

{

Serial1.flush(); // Clear the serial1 buffer.

Serial1.write(0x55); // Send a “distance measure” command to US-100

delay(200); // US100 response time depends on distance.

if (Serial1.available() 》= 2) // at least 2 bytes are in buffer

{

MSByteDistance = Serial1.read(); // Read both bytes

LSByteDistance = Serial1.read();//

TempmmDistance = (MSByteDistance * 256 + LSByteDistance);

Particle.publish(“Raw mm data”, String(TempmmDistance), 60, PRIVATE);

delay(200);

mmDistance = mmDistance + TempmmDistance; // calculate distance in mm. Add to running sum.

if ((TempmmDistance 》 50) && (TempmmDistance 《 MAX_DISTANCE)) // Test that the distance is in range.

{

US100reading.add(TempmmDistance); // put another datum into the buffer for a running median.

} else avgloop--; // discard this datum.

}

}

mmDistance = mmDistance/DataToAvg; // calculate the mean of N measurements.

Serial.print(“Raw mm data: ”);

Serial.print(TempmmDistance);

Median_mm = US100reading.getMedian(); // get the current running median value of mm from sensor to surface of oil.

Particle.publish(“Median_mm”, String(Median_mm), 60, PRIVATE);

Serial.print(“ Median mm data: ”);

Serial.println(Median_mm);

mm_of_oil = ZeroOilmm - Median_mm; // I determined that my boiler quits when mm = 1304.

Particle.publish(“mm_of_oil”, String(mm_of_oil), 60, PRIVATE);

delay(1000); // wait for last publish to finish.

if ((mm_of_oil 》 0) && (mm_of_oil 《 MAX_DISTANCE))

{

ThingSpeak.setField(1, mm_of_oil);

ThingSpeak.setField(7, TempmmDistance);

delay(1000); // wait for last Publish to finish.

// Calculate litres.。..Our tank is 1.10 mm/L

litres_of_oil = 0.909 * mm_of_oil; // Calibrated 2018-02-24 during tank filling.

Particle.publish(“Oil level (L)”, String(litres_of_oil), 60, PRIVATE);

ThingSpeak.setField(6, litres_of_oil);

}

// Monitor the battery voltage

voltage = 0;

for (int z = 1; z 《 101; z++) // It is pretty noisy so we take an average of 100 values.

{

voltage += battCalib * ((analogRead(VBATT) / 4096.0) * 3.3); // battery monitor is via a voltage divider.

}

voltage = (voltage/100);

BattVolts = voltage;

soc = ((voltage - DeadBattVolts) / (FullChargeVolts - DeadBattVolts)) * 100.0;

Particle.publish(“BattVolts”, String(BattVolts, 2), 60, PRIVATE);

ThingSpeak.setField(2,voltage);

delay(1000); // Can only publish 4 variables per second.

Particle.publish(“BattPercent”, String(soc, 1), 60, PRIVATE);

// Monitor the charge/discharge current. Negative values mean the solar panel is effectively charging the battery.

CurCountsDiff = 0;

for (q = 1; q 《 101; q++) // The readings are so noisy, need to average 100 of them.

{

negCurCounts = analogRead(NEGCURPIN);

posCurCounts = (analogRead(POSCURPIN) + posCurOffset);

difference = (posCurCounts - negCurCounts);

CurCountsDiff = CurCountsDiff + difference;

}

CurCountsDiff = (CurCountsDiff/100);

BattCurrent = (currentConversion * (CurCountsDiff));

Particle.publish(“BattCurrent mA”, String(BattCurrent, 0), 60, PRIVATE);

ThingSpeak.setField(4, BattCurrent);

// Send Alerts via Pushbullet:

if ((mm_of_oil 《 50) && (mm_of_oil 》 45)) // Only want Pushbullet to send a few warnings

{

Particle.publish(“Alert”, “Heating Oil Level is 5cm - Refill SOON!”, PRIVATE);

LowOilAlert = HIGH;

}

if (soc 《 battThreshold)

{

Particle.publish(“Alert”, “Oilwatcher battery is very low. Recharge it.”, PRIVATE);

battalert = HIGH;

}

// Read temperature from the US-100 ultrasonic rangefinder’s temp sensor at the top of the tank. The tank air heats up in the sun.

Serial1.flush();

while (Serial1.available() 》= 1) // seemed like flush() was not working so I added this.

{

junk = Serial1.read();

}

Serial1.write(0x50); // send command to request temperature byte.

delay(50); // temp response takes about 2ms after command ends.

if (Serial1.available() 》= 1)

{

US100tempData = Serial1.read();

if ((US100tempData 》 1) && (US100tempData 《 130))

{

US100tempData -= 45; // Correct by the 45 degree offset of the US100.

Particle.publish(“Tank °C”, String(US100tempData), 60, PRIVATE);

ThingSpeak.setField(5, US100tempData);

}

}

// Read temperature from the DS18B20 sensors in electronics box and outside.

BoxCelsius = TempSensors.getTemperature(sensorAddresses[1]); // Will it always find the 1-wire sensor addresses in the same order?

BoxTempStr = String(BoxCelsius, 1);

Particle.publish(“Box °C”, BoxTempStr, PRIVATE);

ThingSpeak.setField(3, BoxTempStr);

OutsideCelsius = TempSensors.getTemperature(sensorAddresses[0]);

OutsideTempStr = String(OutsideCelsius, 1);

Particle.publish(“Outside °C”, OutsideTempStr, PRIVATE);

ThingSpeak.setField(8, OutsideTempStr);

// Send all data to ThingSpeak for graphing and calculations.

ThingSpeak.writeFields(ThingSpeakChannelNumber, ThingSpeakWriteAPIKey);

// give time for temperature to publish before going to sleep.

delay(10000); // In case I need to reprogram it, here is a chance when it is not sleeping.

System.sleep(WAKEPIN, RISING, SleepSecs); // Turn off WiFi and pause execution, preserving variables. Wakes after set # of seconds

// A momentary button on the box allows waking for easier re-programming.

// Hit Flash very soon after hitting the wakeup button. Or just before.

//System.reset(); // This was one way to allow it to not lose its ability connect to wifi when the router‘s IP address changed during sleep.

// Disadvantage is it only loops once thru the code. No variables remembered.

} // end void loop()

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

    关注

    21

    文章

    3608

    浏览量

    169147
收藏 人收藏

    评论

    相关推荐

    实用小知识:如何检测油箱盖是否关闭?

    油箱和加注口周围被认为是高度危险的易爆区域,存在引发火灾的风险。车辆操作员或维修人员容易忘记关闭油箱盖,而直接从油箱中偷盗汽油的现象也在增加。为了解决这些问题,设计师现在打算采用干簧传感器。这种
    的头像 发表于 02-26 11:25 731次阅读
    实用小知识:如何检测<b class='flag-5'>油箱</b>盖是否关闭?

    请问渗的变压器需要做哪些检修和检测?

    2006年曾因瓷瓶垫圈破损漏油进行维修和加油;现几年未做检测, 观察其运行状况,未见异常,现发现变压器四周有渗的迹象,但色正; 常请问各位大虾:现在对变压器需要进行哪些项目的检
    发表于 11-24 06:08

    教你自制实用的夜视

    监控摄像头加带有红外发光二极管和发光二极管驱动器的PCB,制作你自己的夜视!资料包含项目PCB图+线路图+3D打印文件+详细说明
    发表于 09-25 08:16

    斯丹麦德应用案例 | 干簧传感器在汽车油箱盖位置检测上的应用

    电子发烧友网站提供《斯丹麦德应用案例 | 干簧传感器在汽车油箱盖位置检测上的应用.pdf》资料免费下载
    发表于 09-20 13:29 0次下载

    真空泵的结构原理

    盛源无真空泵的结构主要由机械传动部分、机械抽气部分和隔部分组成。机械传动部分分为曲柄和连杆机构,由电动机带动皮带轮,然后通过曲轴、连杆、十字头传递给活塞,由皮带轮的圆周运动变为活塞的直线运动
    发表于 09-12 14:57

    汽车油箱检测电路的设计(2)#传感器

    传感器
    未来加油dz
    发布于 :2023年08月20日 10:00:49

    汽车油箱检测电路的设计(1)#传感器

    传感器
    未来加油dz
    发布于 :2023年08月20日 10:00:26

    如何制作ESP32 CAM板监控机器人汽车

    电子发烧友网站提供《如何制作ESP32 CAM板监控机器人汽车.zip》资料免费下载
    发表于 06-29 10:24 5次下载
    如何<b class='flag-5'>制作</b>ESP32 CAM板<b class='flag-5'>监控</b>机器人汽车

    油箱盖防水气密性测试设备应用

    油箱盖是燃油蒸汽排放系统中非常重要的组成部分,因为考虑到使用环境问题,油箱需要有完全的密封性能,以保证油箱盖不会出现泄露导致漏油甚至自燃的情况。今天连拓精密就给大家演示如何使用压缩空气对油箱
    的头像 发表于 06-29 08:53 330次阅读
    <b class='flag-5'>油箱</b>盖防水气密性测试设备应用

    基于Arduino和超声波传感器构建一个简单的油箱液位指示器电路

    在这篇文章中,我们将学习如何使用 Arduino 和超声波传感器构建一个简单的油箱液位指示器电路。
    的头像 发表于 06-27 18:14 794次阅读
    基于Arduino和超声波传感器构建一个简单的<b class='flag-5'>油箱</b>液位指示器电路

    常压油箱和高压油箱的概念

    汽油是极易挥发性液体,资料显示,在28℃的开放条件下,仅需20分钟就可以挥发55%,如果油箱与大气是开放式连通,超过一天时间油箱内的汽油都会挥发的所剩无几。如果油箱是完全密封状态,汽油挥发后也会使
    的头像 发表于 05-29 15:29 1692次阅读
    常压<b class='flag-5'>油箱</b>和高压<b class='flag-5'>油箱</b>的概念

    汽车油箱盖防水检测重要吗?有什么注意点?-海瑞思

    一、汽车油箱盖防水检测的重要性 1、汽车油箱盖是汽车最重要的零部件之一,它不仅能有效保护汽车油箱内的液体,而且还能有效地防止汽车油箱内的液体泄漏出去,对汽车的正常运行起到重要的作用。因
    的头像 发表于 05-16 14:05 376次阅读

    如何用ESP8266制作一个wifi扫描并显示信息?

    我正在用 ESP8266 制作一个 wifi 扫描并显示信息我正在使用基于 SPI 的诺基亚 1616/C100 显示器。这次我在本地编码 ESP8266,而不是使用 mcu + esp8266
    发表于 05-16 06:35

    如何检修变压器枕?

      变压器枕的检修项目:   1 普通式枕   1)打开枕两侧端盖,清扫内外表面锈蚀及油垢,然后内壁刷上绝缘漆,外壁刷油漆;   2)清扫积污器、
    发表于 04-26 16:41

    如何判断变压器的好坏?

      变压器是在变压器中起着加强绝缘、散热、防腐和灭弧的作用。由于对变压器的质量要求很高,严格的讲,不经过耐压试验和简化试验,很难说明变压器是否合格。但经过长期的实践表明,现场简单判断变压器
    发表于 04-26 16:00