Giter Site home page Giter Site logo

Comments (7)

persquare avatar persquare commented on May 16, 2024

Do I need to run the example of SensorKit using sudo?

No. You should never have to run any of the commands using sudo.

When I tried to run the light example, without sudo I got the following error messages.
[snip]
import pigpio
ImportError: No module named pigpio

For some reason, the pigpio package is not installed on the device.

Also, I tried humidity.calvin with an DHT11. Nothing print out when I used sudo.
pi@raspberrypi:~/calvin-base/calvin/examples/sensor-kit$ sudo csruntime --host localhost -w 0 humidity.calvin

Again, you shouldn't use sudo, but the example should work.

By the way, the pin layout looks wrong. The GND of the sensor is connected at GPIO:21 not an GND pin.

Thanks for pointing that out, that is most likely a bug on our behalf.

I'll look into the above issues.

from calvin-base.

peiworld avatar peiworld commented on May 16, 2024

Thanks, I have two DS18B20 temperature sensors attached. So I am modifying the code (see below) to grab sensor readings from those.

However, I feel that this is not a right way of doing it, neither the original code which reads only the first sensor. I think the sensorID should be passed in as an argument. Right?

Problem with the following code:

  • I cannot use dict within the _read_temp function. It never get to this "print "dict:"+len(temps)"
  • I cannot use appending of string such as temp
    self._temperature+=self._temperature+tmp_temperature
    Is there a syncrhoised block declaration or multithread lock?
# -*- coding: utf-8 -*-

# Copyright (c) 2017 Ericsson AB
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from calvin.runtime.south.calvinsys.io.ds18b20thermometer.BaseDS18B20 import BaseDS18B20
from calvin.utilities.calvinlogger import get_logger
from calvin.runtime.south.plugins.async import async
from os import path
import glob
import json

_log = get_logger(__name__)

class DS18B20(BaseDS18B20):
    """
    Calvinsys object handling DS18B20 temperature sensor
    """
    def init(self, **kwargs):
        self._base_dir = '/sys/bus/w1/devices/'
        self._temperature = None
        self._device_folders = self._find_device_folders()
        self._in_progress = None

    def _find_device_folders(self):
        try :
            device_folders = glob.glob(self._base_dir + '28*')
        except Exception as e:
            _log.warning("Failed to find device file: {}".format(e))
            device_folders = None
        return device_folders
        

    def _read_temp_raw(self, device_file):
        try:
            with open(device_file, 'r') as fp:
                return fp.readlines()
        except:
            return None

    def _read_temp(self):
        temps={}
        for device_folder in self._device_folders:
            lines = self._read_temp_raw(device_folder+'/w1_slave')
            if not lines or lines[0].strip()[-3:] != 'YES':
                # Nothing to read, try again in a second
                self._in_progress = async.DelayedCall(1.0, self._read_temp)
                return

            equals_pos = lines[1].find('t=')
            tmp_temperature=None
            sensorID=path.basename(path.normpath(device_folder))
            if equals_pos != -1:
                temp_string = lines[1][equals_pos + 2:]
                print device_folder+" "+sensorID+" "+temp_string
                tmp_temperature = str(float(temp_string)/1000.0)
                print "test:"+tmp_temperature
            else :
                print "waiting..."
                self._in_progress = async.DelayedCall(1.0, self._read_temp)
        
            # clear in_progress
            self._in_progress = None
            print "test2:" + tmp_temperature
            temps[sensorID]= tmp_temperature
        print "dict:"+len(temps)
        self._temperature = json.dumps(temps)


    def _start_read(self):
        print "_start_read"
        async.call_from_thread(self._read_temp)

    def can_write(self):
        print "can_write"
        return self._in_progress is None

    def write(self, measure):
        print"write"
        self._in_progress = async.DelayedCall(0.0, self._read_temp)

    def can_read(self):
        print "can_read"
        return self._temperature is not None
        
    def read(self):
        print "read"
        _temperature = self._temperature
        self._temperature = None
        return _temperature
        
    def close(self):
        print "close"
        self._device_folders = None

from calvin-base.

persquare avatar persquare commented on May 16, 2024

Thanks, I have two DS18B20 temperature sensors attached. So I am modifying the code (see below) to grab sensor readings from those.
However, I feel that this is not a right way of doing it, neither the original code which reads only the first sensor. I think the sensorID should be passed in as an argument. Right?

Your intuition is correct, there is another way of doing it, and I'm afraid that the explanation is a bit lengthy so bare with me :)

I'll start with an example relevant to your setup:
Assume that we have some pipe system with water flowing from an inlet to an outlet, and we want to measure the temperature at those sites to establish how much energy was lost in the process.

To do that, we need a temperature actor on each site which of course requires us to have a runtime at each site. Actors are completely ignorant of where they execute, so all information about location etc. is contained within the runtime. For simplicity's sake, lets assume that we have given the runtimes the names "inlet" and "outlet", respectively. Using deployment rules, Calvin will deploy a temperature actor on each runtime:

# Incomplete code illustrating deployment rules
t_in : sensor.Temperature()
t_out : sensor.Temperature()
...
apply t_in : node_name("inlet")
apply t_out : node_name("outlet")

The reason for this is that we eventually want sensors to be calvin-compatible units themselves, rather than dumb devices tied to a gateway. So, this is a conscious design decision that we hope will pay off in the long run.
(It makes sense to think about using two battery powered constrained devices communicating over WiFi or BluetoothLE, each having a DS18B20 sensor and running calvin-constrained runtimes.)

What trips things up here is the fact that e.g. a Raspberry Pi is a cheap device capable of handling a multitude of sensors that powerful and very easy to work with. But it is not the kind of device that Calvin was designed for... So while the obvious solution to hook up two sensors with some length of wire to the same RPi is tempting, the "proper" way is to hook up one sensor per runtime, and instantiate two runtimes with different attributes (names "inlet" and "outlet" in this case) and your OK to go.

Actually, you will need two separate Raspberry Pis to make this work, since the driver won't let two runtimes share access to the same sensor. It's in our roadmap to implement a "virtual runtime" to let a single RPi handle this kind of situation.

So, in summary, in addition to being a substrate where actors can execute, a runtime (through its unique set of attributes) represents the physical location of a sensor, and it doesn't make sense to have two identical sensors at the same physical location.

from calvin-base.

peiworld avatar peiworld commented on May 16, 2024

In our modeling, we assume each IoT node will run only one runtime. Each runtime seems to take up to 32MB in RAM. Firing up multiple runtimes seems not ideal even for relatively constrained devices. However, can we achieve ideas like sandboxing if multiple actors running in the same runtime.

I understand that we normally don't have multiple attachments of the same type of sensor at the same location. But in some cases, we may have such deployment situation.

from calvin-base.

persquare avatar persquare commented on May 16, 2024

Have you looked at calvin-constrained https://github.com/EricssonResearch/calvin-constrained? IIRC, the x86 port is (despite its name) a generic ANSI C port and should run on RPi "as is". It shouldn't use more than a 100k or so of RAM. Having two of them, each having a temp sensor, connected to a "host" runtime would allow each sensor to have it's set of attributes etc. We've used this setup to create "proxy-runtimes" for multiple devices connected to RPis.
That said, there is no calvinsys implementation of the ds18b20 driver for the x86 port, but there is one for the ESP8266 (which is what we use most of the time) that could serve as an example.

(It's summer vacation time over here, so responses and definitive answers might be in short supply until mid August I'm afraid...)

from calvin-base.

olaan avatar olaan commented on May 16, 2024

As the author of the issue noted, there is currently no way of specifying which sensor to use if several are present - the runtime will presently always select the first one encountered.

It is straightforward to add support for indexing based on some ordering (e.g. the serial number of the sensor.) This would then be used in the configuration file to either specify a sensor to use for the io.temperature capability, or assign different capabilities to each sensor. The latter would then require the application use different actors for the different sensors rather than using different runtimes to handle the sensors.

A straightforward test of this:

--- a/calvin/runtime/south/calvinsys/io/ds18b20thermometer/raspberry_pi/DS18B20.py
+++ b/calvin/runtime/south/calvinsys/io/ds18b20thermometer/raspberry_pi/DS18B20.py
@@ -28,12 +28,19 @@ class DS18B20(BaseDS18B20):
     def init(self, **kwargs):
         self._base_dir = '/sys/bus/w1/devices/'
         self._temperature = None
-        self._device_file = self._find_device_file()
+       if "index" in kwargs:
+           self._index = kwargs["index"]
+       else :
+           self._index = None
+        self._device_file = self._find_device_file(self._index)
         self._in_progress = None

-    def _find_device_file(self):
+    def _find_device_file(self, idx):
+       if idx is None :
+           idx = 0
+
         try :
-            device_folder = glob.glob(self._base_dir + '28*')[0]
+            device_folder = glob.glob(self._base_dir + '28*')[idx]
             device_file = device_folder + '/w1_slave'
         except Exception as e:
             _log.warning("Failed to find device file: {}".format(e))

And the calvin.conf entry to use the sensor on index 1 is then:

"io.temperature": {
    "module": "io.ds18b20thermometer.raspberry_pi.DS18B20",
    "attributes": {"index": 1}

from calvin-base.

olaan avatar olaan commented on May 16, 2024

I'm closing this issue now. If you have further questions, feel free to open a new one.

Cheers.

from calvin-base.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.