Hi,
Does anyone know if it is possible to reduce the resolution of the dust sensor’s measurements from every 30 seconds to every 10 seconds? If so, can you point me to the place in the code where this parameter can be changed?
Thanks
Hi,
Does anyone know if it is possible to reduce the resolution of the dust sensor’s measurements from every 30 seconds to every 10 seconds? If so, can you point me to the place in the code where this parameter can be changed?
Thanks
Hi @edrjeffery,
You could do that by altering the source of the firmware at this location:
Notice that the time unit is milliseconds, so you’d have to play around with thousands instead.
Then, compile it and flash it with avrdude.
Thank you!
Hi @RobertLucian,
Are you able to briefly describe how I compile and flash the file please?
I’ve tried myself, but I get an “AVR device not responding” error from avrdude. I’ve listed the steps I took below in case that helps at all:
Do you have any ideas of what is going wrong?
Thanks!
Hi @edrjeffery,
Well first of all, you need to have the following configuration for the gpio
programmer in /etc/avrdude.conf
configuration file:
programmer
id = "gpio";
desc = "Use sysfs interface to bitbang GPIO lines";
type = gpio;
reset = 8;
sck = 11;
mosi = 10;
miso = 9;
;
And second of all, when burning the hex file to the grovepi
, you need to run the following commands:
avrdude -c gpio -p m328p -U lfuse:w:0xFF:m
avrdude -c gpio -p m328p -U hfuse:w:0xDA:m
avrdude -c gpio -p m328p -U efuse:w:0x05:m
avrdude -c gpio -p m328p -U flash:w:grove_pi_firmware.hex
This is all you need to do in order to flash a compiled program to the GrovePi.
Please let me know if you have other issues.
Thank you!
Hi @RobertLucian,
I followed the steps above, but I now get an IO error when I run the grove_dust_sensor.py code. The error code is 121 (Remote I/O error). I have double checked that Remote IO and I2C are both on in the raspi-config settings. I have also turned off the Pi, disconnected the GrovePi and tried again, but that hasn’t helped. I couldn’t find a solution online so I have run the GrovePi troubleshooting script, with the output shown below:
Check space left
================
Filesystem Size Used Avail Use% Mounted on
/dev/root 7.2G 4.6G 2.3G 68% /
devtmpfs 213M 0 213M 0% /dev
tmpfs 217M 0 217M 0% /dev/shm
tmpfs 217M 3.5M 214M 2% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 217M 0 217M 0% /sys/fs/cgroup
/dev/mmcblk0p1 43M 22M 21M 51% /boot
tmpfs 44M 4.0K 44M 1% /run/user/1000
Check for dependencies
======================
python 2.7.13-2 install ok installed
python-pip 9.0.1-2+rpt2 install ok installed
git 1:2.11.0-3+deb9u3 install ok installed
libi2c-dev 3.1.2-3 install ok installed
python-serial 3.2.1-1 install ok installed
python-rpi.gpio 0.6.3~stretch-1 install ok installed
i2c-tools 3.1.2-3 install ok installed
python-smbus 3.1.2-3 install ok installed
arduino 2:1.0.5+dfsg2-4.1 install ok installed
minicom 2.7-1.1 install ok installed
scratch 1.4.0.6~dfsg1-5 install ok installed
find: ‘/run/user/1000/gvfs’: Permission denied
wiringPi Not Found (ERR)
find: ‘/run/user/1000/gvfs’: Permission denied
I2C still in blacklist (ERR)
SPI still in blacklist (ERR)
Check for addition in /modules
==============================
I2C-dev already there
i2c-bcm2708 already there
spi-dev already there
Hardware revision
=================
gpio version: 2.44
Copyright (c) 2012-2017 Gordon Henderson
This is free software with ABSOLUTELY NO WARRANTY.
For details type: gpio -warranty
Raspberry Pi Details:
Type: Pi Zero, Revision: 03, Memory: 512MB, Maker: Sony
* Device tree is enabled.
*--> Raspberry Pi Zero Rev 1.3
* This Raspberry Pi supports user-level GPIO access.
Check the /dev folder
=====================
i2c-1
ttyAMA0
USB device status
=================
Bus 001 Device 006: ID 0bda:8152 Realtek Semiconductor Corp.
Bus 001 Device 005: ID 0a5c:bd1e Broadcom Corp.
Bus 001 Device 004: ID 413c:2107 Dell Computer Corp.
Bus 001 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 002: ID 1a40:0101 Terminus Technology Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 1: Dev 3, If 1, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 1: Dev 3, If 2, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 1: Dev 3, If 0, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 2: Dev 4, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
|__ Port 3: Dev 5, If 0, Class=Vendor Specific Class, Driver=brcmfmac, 480M
|__ Port 4: Dev 6, If 0, Class=Vendor Specific Class, Driver=r8152, 480M
Raspbian for Robots Version
===========================
cat: /home/pi/di_update/Raspbian_For_Robots/Version: No such file or directory
Hostname
========
raspberrypi
Checking for Atmega chip
========================
avrdude: Version 6.3
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "/etc/avrdude.conf"
User configuration file is "/root/.avrduderc"
User configuration file does not exist or is not a regular file, skipping
avrdude: Can't find programmer id "gpio"
Valid programmers are:
2232HIO = FT2232H based generic programmer [/etc/avrdude.conf:412]
4232h = FT4232H based generic programmer [/etc/avrdude.conf:440]
arduino = Arduino [/etc/avrdude.conf:360]
arduino-ft232r = Arduino: FT232R connected to ISP [/etc/avrdude.conf:764]
atmelice = Atmel-ICE (ARM/AVR) in JTAG mode [/etc/avrdude.conf:1114]
atmelice_dw = Atmel-ICE (ARM/AVR) in debugWIRE mode [/etc/avrdude.conf:1130]
atmelice_isp = Atmel-ICE (ARM/AVR) in ISP mode [/etc/avrdude.conf:1138]
atmelice_pdi = Atmel-ICE (ARM/AVR) in PDI mode [/etc/avrdude.conf:1122]
avr109 = Atmel AppNote AVR109 Boot Loader [/etc/avrdude.conf:885]
avr910 = Atmel Low Cost Serial Programmer [/etc/avrdude.conf:721]
avr911 = Atmel AppNote AVR911 AVROSP [/etc/avrdude.conf:892]
avrftdi = FT2232D based generic programmer [/etc/avrdude.conf:386]
avrisp = Atmel AVR ISP [/etc/avrdude.conf:608]
avrisp2 = Atmel AVR ISP mkII [/etc/avrdude.conf:628]
avrispmkII = Atmel AVR ISP mkII [/etc/avrdude.conf:622]
avrispv2 = Atmel AVR ISP V2 [/etc/avrdude.conf:615]
buspirate = The Bus Pirate [/etc/avrdude.conf:633]
buspirate_bb = The Bus Pirate (bitbang interface, supports TPI) [/etc/avrdude.conf:640]
butterfly = Atmel Butterfly Development Board [/etc/avrdude.conf:878]
butterfly_mk = Mikrokopter.de Butterfly [/etc/avrdude.conf:906]
bwmega = BitWizard ftdi_atmega builtin programmer [/etc/avrdude.conf:751]
C232HM = FT232H based module from FTDI and Glyn.com.au [/etc/avrdude.conf:509]
c2n232i = serial port banging, reset=dtr sck=!rts mosi=!txd miso=!cts [/etc/avrdude.conf:1294]
dasa = serial port banging, reset=rts sck=dtr mosi=txd miso=cts [/etc/avrdude.conf:1266]
dasa3 = serial port banging, reset=!dtr sck=rts mosi=txd miso=cts [/etc/avrdude.conf:1280]
diecimila = alias for arduino-ft232r [/etc/avrdude.conf:775]
dragon_dw = Atmel AVR Dragon in debugWire mode [/etc/avrdude.conf:1041]
dragon_hvsp = Atmel AVR Dragon in HVSP mode [/etc/avrdude.conf:1032]
dragon_isp = Atmel AVR Dragon in ISP mode [/etc/avrdude.conf:1014]
dragon_jtag = Atmel AVR Dragon in JTAG mode [/etc/avrdude.conf:1005]
dragon_pdi = Atmel AVR Dragon in PDI mode [/etc/avrdude.conf:1050]
dragon_pp = Atmel AVR Dragon in PP mode [/etc/avrdude.conf:1023]
flip1 = FLIP USB DFU protocol version 1 (doc7618) [/etc/avrdude.conf:1161]
flip2 = FLIP USB DFU protocol version 2 (AVR4023) [/etc/avrdude.conf:1168]
ft232r = FT232R Synchronous BitBang [/etc/avrdude.conf:739]
ft245r = FT245R Synchronous BitBang [/etc/avrdude.conf:728]
jtag1 = Atmel JTAG ICE (mkI) [/etc/avrdude.conf:919]
jtag1slow = Atmel JTAG ICE (mkI) [/etc/avrdude.conf:924]
jtag2 = Atmel JTAG ICE mkII [/etc/avrdude.conf:954]
jtag2avr32 = Atmel JTAG ICE mkII im AVR32 mode [/etc/avrdude.conf:987]
jtag2dw = Atmel JTAG ICE mkII in debugWire mode [/etc/avrdude.conf:969]
jtag2fast = Atmel JTAG ICE mkII [/etc/avrdude.conf:948]
jtag2isp = Atmel JTAG ICE mkII in ISP mode [/etc/avrdude.conf:960]
jtag2pdi = Atmel JTAG ICE mkII PDI mode [/etc/avrdude.conf:996]
jtag2slow = Atmel JTAG ICE mkII [/etc/avrdude.conf:943]
jtag3 = Atmel AVR JTAGICE3 in JTAG mode [/etc/avrdude.conf:1058]
jtag3dw = Atmel AVR JTAGICE3 in debugWIRE mode [/etc/avrdude.conf:1074]
jtag3isp = Atmel AVR JTAGICE3 in ISP mode [/etc/avrdude.conf:1082]
jtag3pdi = Atmel AVR JTAGICE3 in PDI mode [/etc/avrdude.conf:1066]
jtagkey = Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2 [/etc/avrdude.conf:447]
jtagmkI = Atmel JTAG ICE (mkI) [/etc/avrdude.conf:911]
jtagmkII = Atmel JTAG ICE mkII [/etc/avrdude.conf:935]
jtagmkII_avr32 = Atmel JTAG ICE mkII im AVR32 mode [/etc/avrdude.conf:978]
linuxgpio = Use the Linux sysfs interface to bitbang GPIO lines [/etc/avrdude.conf:1188]
linuxspi = Use Linux SPI device in /dev/spidev* [/etc/avrdude.conf:1215]
lm3s811 = Luminary Micro LM3S811 Eval Board (Rev. A) [/etc/avrdude.conf:570]
mib510 = Crossbow MIB510 programming board [/etc/avrdude.conf:672]
mkbutterfly = Mikrokopter.de Butterfly [/etc/avrdude.conf:900]
nibobee = NIBObee [/etc/avrdude.conf:847]
o-link = O-Link, OpenJTAG from www.100ask.net [/etc/avrdude.conf:541]
openmoko = Openmoko debug board (v3) [/etc/avrdude.conf:552]
pavr = Jason Kyle's pAVR Serial Programmer [/etc/avrdude.conf:1147]
pickit2 = MicroChip's PICkit2 Programmer [/etc/avrdude.conf:1154]
ponyser = design ponyprog serial, reset=!txd sck=rts mosi=dtr miso=cts [/etc/avrdude.conf:1244]
siprog = Lancos SI-Prog <http://www.lancos.com/siprogsch.html> [/etc/avrdude.conf:1257]
stk500 = Atmel STK500 [/etc/avrdude.conf:658]
stk500hvsp = Atmel STK500 V2 in high-voltage serial programming mode [/etc/avrdude.conf:693]
stk500pp = Atmel STK500 V2 in parallel programming mode [/etc/avrdude.conf:686]
stk500v1 = Atmel STK500 Version 1.x firmware [/etc/avrdude.conf:665]
stk500v2 = Atmel STK500 Version 2.x firmware [/etc/avrdude.conf:679]
stk600 = Atmel STK600 [/etc/avrdude.conf:700]
stk600hvsp = Atmel STK600 in high-voltage serial programming mode [/etc/avrdude.conf:714]
stk600pp = Atmel STK600 in parallel programming mode [/etc/avrdude.conf:707]
ttl232r = FTDI TTL232R-5V with ICSP adapter [/etc/avrdude.conf:811]
tumpa = TIAO USB Multi-Protocol Adapter [/etc/avrdude.conf:591]
UM232H = FT232H based module from FTDI and Glyn.com.au [/etc/avrdude.conf:482]
uncompatino = uncompatino with all pairs of pins shorted [/etc/avrdude.conf:787]
usbasp = USBasp, http://www.fischl.de/usbasp/ [/etc/avrdude.conf:822]
usbasp-clone = Any usbasp clone with correct VID/PID [/etc/avrdude.conf:858]
usbtiny = USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/ [/etc/avrdude.conf:869]
wiring = Wiring [/etc/avrdude.conf:353]
xplainedmini = Atmel AVR XplainedMini in ISP mode [/etc/avrdude.conf:1098]
xplainedmini_dw = Atmel AVR XplainedMini in debugWIRE mode [/etc/avrdude.conf:1106]
xplainedpro = Atmel AVR XplainedPro in JTAG mode [/etc/avrdude.conf:1090]
Checking I2C bus for devices
============================
Checking I2C bus 0
==================
Error: Could not open file `/dev/i2c-0' or `/dev/i2c/0': No such file or directory
Checking I2C bus 1
==================
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- 04 -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Checking for firmware version
=============================
Traceback (most recent call last):
File "/home/pi/GrovePi/Software/Python/grove_firmware_version_check.py", line 40, in <module>
print("GrovePi has firmware version: %s" %grovepi.version())
File "/home/pi/GrovePi/Software/Python/grovepi.py", line 266, in version
return "%s.%s.%s" % (number[1], number[2], number[3])
TypeError: 'int' object has no attribute '__getitem__'
@RobertLucian My guess is that it is a firmware issue (given the GrovePi is detected by i2cdetect). All I have done is change the 30000 to 10000, compiled using the Arduino IDE and then flashed using your instructions above, so I’m not sure what could have gone wrong…
I also forgot to mention that when creating a new ‘gpio’ programmer, I kept on getting error messages saying the avrdude.conf file could not be read. So I edited the ‘linuxgpio’ programmer to be exactly the same, but just a different name. I’m not sure if this will have made a difference, but it seemed to work when flashing an old (unchanged) hex file.
Sorry for another message, but I’ve been working on this over the weekend so far and wanted to provide an update. I think I have narrowed the issue down to the compiling of the grove_pi_v1_2_7.ino file.
From this, I have concluded that it must be an issue with the compiling, since your already compiled hex file can be flashed and works, but when I compile the relevant .ino file myself and flash it does not work.
Hope that helps the troubleshooting in some way.
I have an idea for how to solve this: would you please compile the edited .ino file (10000ms instead of 30000ms) at your end and send the hex file over to me? If you have the correct Arduino IDE set up, then this should then work on my GrovePi once it is flashed. What do you think?
Ed
Hi @edrjeffery,
Yep, I’ve compiled it on my own and I’ve changed the timing from 30 seconds to just 10. I haven’t tested it, though it should work.
firmware.cpp (33.5 KB)
Because I can’t upload executables in here, I changed the program’s extension to cpp
, so keep this in mind.
Let me know how it goes.
Thank you!
Hi @RobertLucian,
Thank you for sending that over. I have flashed it and I no longer get the error, which is a good sign. However, I do not get a reading every 10 seconds. It seems more random, and it can take over a minute between measurements. Any idea what is going on?
Thanks!
Hi @edrjeffery,
Not yet, but I’m already investigating the problem. Which by the way, if you happen to find a solution faster than me, I welcome it. So please let me know if you find something.
Thank you!
Hi @edrjeffery,
I think I have something you can toy around. So for the GrovePi I have created 3 additional functions which give you the following functionalities:
setDustSensorInterval(interval_ms)
- sets the dust’s sensor interval for the sample rate (i.e. 30,000ms or 10,000ms or such).
getDustSensorInterval()
- retrieves you the current interval set for the dust sensor. Be aware that on each power up the GrovePi will default to 30,000
ms so you’ll have to reset it in a python script.
dustSensorReadMore(blocking = True)
- retrieves you the Low Pulse Occupancy variable, the percentage which reflects the LPO time with respect to the entire interval spent for a sample and the concentration measured in pcs/238ml (=0.01cf)
. If there’s anyone who wants to better understand the relationship between all these 3 returned variables, check the added graph.
Now, since all these are not a part of the official firmware yet, here are the functions you need to add to the grovepi
module:
dust_sensor_int_cmd=[9]
dust_sensor_read_int_cmd=[6]
def dustSensorRead():
"""
By default, the sample rate is set to 1 at every 30 seconds and this
function was written only for that interval.
If you wish to use a different
interval, then use dustSensorReadMore function. To set a
different interval, use setDustSensrInterval function.
"""
write_i2c_block(address, dus_sensor_read_cmd + [unused, unused, unused])
time.sleep(.2)
data_back= bus.read_i2c_block_data(address, 1)[0:6]
if data_back[0]!=255:
lowpulseoccupancy=(data_back[3] * 65536 + data_back[2] * 256 + data_back[1])
return [data_back[0], lowpulseoccupancy]
else:
return [-1,-1]
def setDustSensorInterval(interval_ms):
byte1 = interval_ms & 0xFF
byte2 = interval_ms >> 8
write_i2c_block(address, dust_sensor_int_cmd + [byte1, byte2] + [unused])
time.sleep(.2)
def getDustSensorInterval():
write_i2c_block(address, dust_sensor_read_int_cmd + 3 * [unused])
time.sleep(.2)
data_back = bus.read_i2c_block_data(address, 1)[0:2]
if -1 in data_back: return -1
interval = data_back[0] + data_back[1] * 256
return interval
def dustSensorReadMore(blocking = True):
sampletime_ms = getDustSensorInterval()
found, lpo = dustSensorRead()
while found in [0, -1] and blocking is True:
time.sleep(1.0)
found, lpo = dustSensorRead()
if found in [0, -1] and blocking is False:
return (-1, -1, -1)
percentage = lpo * 100.0 / sampletime_ms
concetration = 1.1 * percentage ** 3 - 3.8 * percentage ** 2 + 520 * percentage + 0.62
return (lpo, percentage, concetration)
And the firmware you need to burn in order for all these 3 new additional functions to work is uploaded here: firmware.cpp (33.8 KB)
One thing I have noticed is that if you pool the information too fast, the found
variable (or data_back[0]
) is no longer set to 1
when a new value is calculated. I think this happens because the current firmware doesn’t separate the ISR and the main loop the right way and thus, at some point dust_latest
variable gets set to 0 before it’s sent to master (the Raspberry Pi).
Let me know if you encounter any issues. I’m waiting for some feedback from you.
Thank you!
@RobertLucian, how do I edit the grovepi
module itself? I have updated thegrovepi.py
file with your additional code, but I realise this isn’t the actual python module. The python module is located /usr/local/lib/python2.7/dist-packages/grovepi-1.0.0-py2.7.egg/grovepi.py
, which I cannot see a way to edit.
@RobertLucian I found the setup.py
script, which I ran. I now get global name 'dust_sensor_read_int_cmd' is not defined
error. Do I need to add this variable to the code?
Hi @edrjeffery,
You need to run the setup.py
like in the following:
sudo python setup.py install --force # for python 2
sudo python3 setup.py install --force # for python 3
These 2 commands will install you the grovepi
package for both versions of Python. You might also be interested in using the reload
built-in function to reload a module when running a python instance from the command line.
As for those variable(s) that you’re getting errors for, I have edited my previous answer with the variables you need to add.
Thank you!
Hi @RobertLucian,
I added in the missing variables, but in python form rather than C form. Or was that not correct? I then ran both the commands listed above and I don’t get an errors.
However, there still seems to be an issue with the timing. This is my test code:
grovepi.dust_sensor_en()
sample_ms = grovepi.getDustSensorInterval()
print("Sample ms:", sample_ms)
grovepi.setDustSensorInterval(10000)
sample_ms = grovepi.getDustSensorInterval()
print("Sample ms:", sample_ms)
while True:
try:
lpo, percentage, concentration = grovepi.dustSensorReadMore()
print(lpo, percentage, concentration)
except IOError:
print("Error")
My sample_ms print statements both print out 65280 (?). I timed the interval between the measurements returned and it is still about 30 seconds. Am I doing something wrong?
Thanks
Hi @edrjeffery,
Must have been the tiredness I had. I gave you the “constants” for the firmware and not those of the library in Python. I edited the answer again.
Let me know if this time it works for you.
Thank you!
Hi @RobertLucian,
Sorry, I should have been clearer. I had made those changes already as I based the syntax on the other constant definitions in the file. So even with those changes, the actual interval between measurements is around 30 seconds and the getDustSensorInterval
still returns 65280.