Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Adding support for OneWire #18

Open
djbwise opened this Issue · 23 comments

8 participants

@djbwise

Where and how do you guys envision one adding support for things like this: https://www.sparkfun.com/products/11050?

Would this be useful as part of the library/framework? Otherwise it obviously can just be a component in my existing project.

Also, what are the thoughts of adding more libraries like this to the arduino bootstrap, that can be called from ruby. This would allow us to take advantage of already written arduino libraries.

@austinbv
Owner

This is just an analog sensor, so you can use it now. It would not be too difficult to add utility library around the sensor it's self and we can merge that in.

@vickash
Collaborator

Re: actual OneWire support.

Some of the work required for OneWire support is already in #34, namely passing arbitrary length strings in the sent message protocol. You don't want to be searching for the device each time. Instead receive the address the first time it gets used (in some kind of setup function written on the Arduino), store it and send it back on subsequent requests.

The current protocol for receiving messages should be able to handle receiving OneWire hex data easily, but could probably be improved.

Where it'll get tricky is having multiple components on the same pin. May need to abstract Pin into its own class.

@austinbv
Owner

Oh I did not see that this is a OneWire component

@nixpulvis

OneWire, I2C, SPI, UART (maybe) could all fall under the same umbrella of IO like operations from the Arduino. I say IO "like" because they might require slightly different parameters.

@vickash
Collaborator

I already have in mind an abstraction like Components::Core::Bus for the first three, which would share a lot of functionality. Components connected to a bus will probably have to be modeled differently than existing components, taking a type of Bus instead of a Board object.

Things like software serial, LCD, servos, or anything that follows the pattern of sending commands that gets interpreted into calls to native Arduino libraries, could be abstracted into another superclass. Something like Components::Core::NativeLibrary.

And then shift registers. We could model a shift register as a "board" with only digital output pins. If the SSD class, for example, could take either a ShiftRegister or a Board, it would be possible to connect with 1 pin if you have a shift register, and 7 if you don't, making it much more useful.

If anyone wants to steal an idea and submit a pull request, feel free.

@nixpulvis

Might I add in some thoughts I had in class today.

A Bus is the generic communication term for all data between components. So by that logic the dino -> arduino communication is on a bus, same as any potential arduino -> other. If all the named busses have ruby classes and arduino classes for properly sending, receiving and relaying communications, the system is complete.

For example. I want to send a UART message on the arduino I could write something like.

board.uart[0].write("hello world!")

And the system takes care of the transmission of that command to the arduino over whatever is in place todo so. Considerations should be looping messages, and command message parsing speed.

Most of this isn't ground breaking, but moving the logic for all communication into the same area seems logical.

@vickash
Collaborator

I mean "bus" in the sense of a bus connected to the board's IO pins. Communication between Ruby and the board is already encapsulated in the TxRx classes, which could indeed inherit from an eventual Bus class.

Software serial support is already in progress: #53, and adding support for hardware UARTs (like on the Mega and Due) should be trivial once this is duplex.

The implementation looks like:

board = Dino::Board.new(Dino::TxRx::Serial.new)
serial = Dino::Components::SoftwareSerial.new(
                     board: board,
                     pins: {rx: 10, tx: 11},
                     baud: 19200
         )
serial.puts "hello world!"
@cdcarter

I think that a Bus class in opposition to Board for a component to connect to is not a terrible idea! I don't have any I2C or OneWire parts laying around so I don't have any reason to start hacking on this (besides, I really gotta finish my printer component once I finish moving), but it feels like it's going the right direction.

That being said, I think that the Bus that I2C and OneWire would want to inherit from would be different than what TxRx is doing. Maybe my mind is exaggerating the difference but though the class hierarchy might feel nice, I think they are implementing fundamentally different things.

I'm probably just scared of Bus-es hosting Bus-es hosting Bus-es.

@justinledwards

I have two of these sensors and 5 of the DHT11 sensors. I'll definitely need to figure this stuff out soon.

@vickash
Collaborator

Setting up a class for the OneWire bus and attaching components to it the way I describe will take some work. To speed things up, we could follow the same pattern the LCD library uses to get a single component on a pin working, and then adapt that later on.

@yanzay

Is it still planned to add OneWire support? I'd like to participate.

@vickash
Collaborator
@yanzay

I use DS18B20 temperature sensors in my project, so I really need this functionality too. But I'm not sure I have full understand of OneWire protocol now, will continue my research.

@vickash
Collaborator
@yanzay

Could we use DallasTemperature library for this purpose? Will it be ok if we include it to sketches?

@vickash
Collaborator
@yanzay

BTW, maybe we should think about separating things like LCD, DallasTemperature to modules (or "custom" sketches)?

@vickash
Collaborator

Switch to 0.12.0 branch and look inside src/lib. We’ve already started doing that. Not separate sketches, but separate source files that then get linked back in Dino.h and utilized in Dino.cpp. Dino.h is then linked in the main sketch which just does tx/rx stuff.

That library looks workable. Why don’t you give it a shot?

Assuming you want to use that library, I'd say just stick everything into Dino.cpp and Dino.h. Creating a wrapper class as with DinoLCD is overkill.

To make it work, all you need to do is create a function inside Dino.cpp that calls the library and reads the sensor (add it to the header file too), and make sure it gets called in Dino.cpp's main switch statement when a specific command number (you should probably use 14) is given in a message. Here's how:

In Dino.h:

#include "OneWire.h"
#include "DallasTemperature.h"
class Dino {
  ...
  private:
    ...
    void handleOneWire(); //cmd = 14
    ...
  ...
}

In Dino.cpp:

void Dino::process() {
  ...
  switch(cmd) {
    ...
    case 14: handleOneWire(); break;
    ...
  }
  ...
}

void Dino::handleOneWire() {
  // Do stuff that uses the DallasTemperature library inside here.
  // The OneWire instance and library instance should initialize (and die) inside this function.
  // This way we can dynamically choose which pin to read each time, allowing multiple sensors via multiple pins

  // In here, the parsed message data that ruby sent is available as variables:
  // pin     : integer that maps directly to a pin on the board (up to 4 digits)
  // pinStr  : char array version of above
  // val     : integer intended for sending a "value", eg. 0-255 for pwm control (up to 4 digits)
  // pinStr  : char array version of above
  // auxMsg  : up to 255 char array

  // To return a message to ruby. simply write to the variable called "response" with the pin and result separated by a colon ":"
  // Adjust the precision to suit your needs. response can be up to 15 chars.
  sprintf(response, "%02d:%02d", pin, temp);
}

NOTE: ... = omitted stuff

Look at the Dino::Message class in ruby to see how the message is constructed before it's sent to the board.

Also look at the Dino::Components::DHT classes, which give you a good prototype to work with.

You will need exactly the same mixins that those classes use.

You'll need to implement a #_read method which sends the message to tell the board to read the sensor in the first place, just like the DHT does. You can just call Dino::Message.encode with the data instead of making a custom function inside the Board class. We need to stop doing that especially for native libraries.

Depending on what data you put into the "response" variable on the arduino side, you may or may not have to override #update with some form of hexadecimal conversion that passes a usable number to the callbacks. For now it's probably a good idea to convert to celsius on the board and send that. You could at least convert the value (string) received with #to_f so all the callbacks don't need to worry about doing that.

Lastly, please submit the pull against the 0.12.0 branch. My explanation apples to that and a lot of changes from 0.11 to 0.12 were actually about making this type of expansion easier.

@yanzay

Oh, thanks for detailed explanation! I'll do it.

@vickash
Collaborator

Nice. Even if you don't get it fully working, make a pull request and I'll see if I can help.

@MinasMazar

I noticed OneWire libs are not included in DinoCLI::Generator::LIB_FILENAMES. Is there a particular reason for this?

@vickash
Collaborator

You're right. They aren't included in there because the files themselves aren't included in the repository yet. I had installed the OneWire library so long ago, that when I started adding DS18B20 support, I forgot it wasn't part of the IDE.

I'll add the library itself and the missing references into the wip branch.

The library you need is, in fact, the one from here: http://www.pjrc.com/teensy/td_libs_OneWire.html. In the meantime, you should be able to unzip, drop the .h and .cpp files into the sketch folder and it will work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.