Welcome Guest! To enable all features please Login or Register.
Options
Go to last post Go to first unread
IngmarGuillaume  
#1 Posted : Sunday, April 05, 2015 2:50:49 PM(UTC)
IngmarGuillaume

Rank: Member

Groups: BetaUser, Registered
Joined: 4/4/2015(UTC)
Posts: 25

Thanks: 3 times
Was thanked: 1 time(s) in 1 post(s)
Can anyone give me a lead on how to program a custom node that interfaces with an I2C device (like the I2C Grove sensors)

I2C capability would open up a world of sensors and devices.
EmbrioAdmin  
#2 Posted : Sunday, April 05, 2015 3:19:03 PM(UTC)
EmbrioAdmin

Rank: Administration

Groups: Administrators
Joined: 12/11/2014(UTC)
Posts: 661

Thanks: 1 times
Was thanked: 36 time(s) in 33 post(s)
I haven't tried any i2c stuff yet, I should though. I'll get one of those grove sensors to try, and I'll see if I can put together an example project of two Arduinos talking with i2c.

I think it should be pretty easy. First, use the Include Files form to tell Embrio where the .h and .cpp files are that you want to use in the project and they will be copied to the compile directory. Get to that form from the view menu or by right clicking on a custom Arduino node. Then add the include lines in the Includes section of a node.

Also note that you'll want to leave out any code that has to do with timing when making a custom Arduino node (no delay() calls). When you add a new code block to an Arduino node it defaults to "every update". Then notice the refresh rate on the bottom right of the screen. The code in the Every Update code block will run that many times per second.

With the non-licensed version of Embrio you can only work in connected mode, where the Arduino is communicating with the computer via the serial cable. If the i2c library needs to use the serial port that will be a problem. I'll do some tests and update this thread, but if you manage to get something working (or have trouble) please update as well!
EmbrioAdmin  
#3 Posted : Sunday, April 05, 2015 4:38:17 PM(UTC)
EmbrioAdmin

Rank: Administration

Groups: Administrators
Joined: 12/11/2014(UTC)
Posts: 661

Thanks: 1 times
Was thanked: 36 time(s) in 33 post(s)
I just got one Nano reading a sensor and sending its value to another Nano via I2C so the second project can use the value. There was a bug I had to fix to get it to work though. I'll include the bug fix in the next installer and write up a tutorial project this week.
IngmarGuillaume  
#4 Posted : Monday, April 06, 2015 12:12:50 AM(UTC)
IngmarGuillaume

Rank: Member

Groups: BetaUser, Registered
Joined: 4/4/2015(UTC)
Posts: 25

Thanks: 3 times
Was thanked: 1 time(s) in 1 post(s)
Lol Admin, you ARE on top of it. I'm glad I paid that $50. Hardly ever seen support that fast.
EmbrioAdmin  
#5 Posted : Monday, April 06, 2015 6:38:39 PM(UTC)
EmbrioAdmin

Rank: Administration

Groups: Administrators
Joined: 12/11/2014(UTC)
Posts: 661

Thanks: 1 times
Was thanked: 36 time(s) in 33 post(s)
Just posted a new version (1.1.5.0) with some bug fixes that make this possible. I'll make an official tutorial soon, but wanted to post here first.

This project has 2 Arduino Nanos. One reads a potentiometer value and sends it via I2C to the other Nano that uses the value to drive an LED. Instead of a potentiometer it would be very useful for the slave Nano to be reading a temperature and humidity sensor, or other sensor which is really slow, and sending that value to the master Nano that's running the main program.

Master / Slave nano setup.

Simply connect the Nanos by attaching pins A4 and A5 to each-other, and attaching the slave to the master's power and ground.

You need two projects, one for each Arduino. The slave simply reads an analog input, and writes the value via I2C.

I2C Slave

The master sets an interrupt to read the value and set an output activation, which is connected to an Analog Output to control an LED. If you check the profiler for this node you'll notice that the custom Arduino node claims to take no time at all. The timing test only works on code defined in an update code block, not in the deceleration block. I'll have to do some work to get timing to work on interrupt functions. It's something to keep in mind for now, but probably shouldn't cause any problems unless you have a lot of other stuff going on in your project.

I2C Master

The I2C read and write nodes are available from the Library tab in Embrio, or you can copy and past the XML from their description pages:
I2C Write Node
I2C Read Node

This should act as a template for making custom Arduino nodes that do I2C communication. I haven't tried other examples yet, but I think now that this example is working they should be pretty straight forward.
IngmarGuillaume  
#6 Posted : Tuesday, April 07, 2015 3:21:08 PM(UTC)
IngmarGuillaume

Rank: Member

Groups: BetaUser, Registered
Joined: 4/4/2015(UTC)
Posts: 25

Thanks: 3 times
Was thanked: 1 time(s) in 1 post(s)
I tried your guideline on a TH02 temperature/humidity high accuracy sensor from Seeedstudio, using this code. The sketch runs in the Arduino IDE, and I tried to translate it into Embrio. It compiled (after a few tries, ;-) ) without errors, yet nothing appears on the outputs.

What am I doing wrong?

The generated node is below:

<Nodes>
<Node>
<UniqueID>7eecc49d-7ed1-4ae3-add0-f48df17957cd</UniqueID>
<AssemblyType>Embrio.NodeEngine.AgentController.Nodes.AgentControllerCustomArduinoNode</AssemblyType>
<NodeType>Custom Arduino Node</NodeType>
<UserDefinedName></UserDefinedName>
<Description>A node that lets you write any Arduino code to interact with the Arduino hardware. Can be both an input and output.</Description>
<NodeColor>201,204,227,255</NodeColor>
<X>0</X>
<Y>0</Y>
<Width>834</Width>
<IncludeCode>#include &lt;arduino.h&gt;
#include &lt;TH02.h&gt;
#include &lt;I2C.h&gt;</IncludeCode>
<DeclerationCode>// Instantiate TH02 sensor
TH02 sensor;
uint8_t devID;
int16_t temp, rh, rh_comp;</DeclerationCode>
<SetupCode>I2c.begin();
I2c.pullup(true); // Enable I2C Internal pullup
I2c.setSpeed(1); // Set I2C to 400Khz
// TH02 ID is 4 MSB
devID = sensor.getId() &gt;&gt; 4;</SetupCode>
<ImageName>arduino.png</ImageName>
<InfoURL></InfoURL>
<CodeDefinitions>
<CodeDefinition>
<UpdateCondition>EveryUpdate</UpdateCondition>
<Code>// Get temperature calculated
sensor.startTempConv();
sensor.waitEndConversion();
temp = sensor.getConversionValue();
Output_Temperature = sensor.getLastRawTemp()/100.0 ;

// Convert humidity
sensor.startRHConv();
sensor.waitEndConversion();
rh = sensor.getConversionValue();
Output_Raw_Humidity = sensor.getLastRawRH()/100.0 ;
Output_Compensated_Humidity = sensor.getConpensatedRH(0)/100.0 ;</Code>
<UniqueID>15dc4bee-78ba-47ce-9c50-6742589a1376</UniqueID>
</CodeDefinition>
</CodeDefinitions>
<Inputs></Inputs>
<Outputs>
<Output>
<UniqueID>47956206-4569-4151-bafe-eddbc6bc597d</UniqueID>
<DefinitionID>00000000-0000-0000-0000-000000000000</DefinitionID>
<DefaultName>Activation</DefaultName>
<CustomName>Temperature</CustomName>
<IsDisplayed>True</IsDisplayed>
<IsNative>False</IsNative>
<TypeName>Numeric</TypeName>
<IsOutsideConnection>False</IsOutsideConnection>
<IOType>Embrio.NodeEngine.NodeIO.NumericNodeOutput</IOType>
<ShowGraph>True</ShowGraph>
<LinkedIOID>00000000-0000-0000-0000-000000000000</LinkedIOID>
<IsUserAdded>True</IsUserAdded>
<MinValue>0</MinValue>
<MaxValue>1</MaxValue>
<UseNegativeRange>False</UseNegativeRange>
<CanUseNegativeRange>True</CanUseNegativeRange>
</Output>
<Output>
<UniqueID>01ffcd6a-2426-41eb-90fe-fee04e14a4ec</UniqueID>
<DefinitionID>00000000-0000-0000-0000-000000000000</DefinitionID>
<DefaultName>Activation 1</DefaultName>
<CustomName>Raw_Humidity</CustomName>
<IsDisplayed>True</IsDisplayed>
<IsNative>False</IsNative>
<TypeName>Numeric</TypeName>
<IsOutsideConnection>False</IsOutsideConnection>
<IOType>Embrio.NodeEngine.NodeIO.NumericNodeOutput</IOType>
<ShowGraph>True</ShowGraph>
<LinkedIOID>00000000-0000-0000-0000-000000000000</LinkedIOID>
<IsUserAdded>True</IsUserAdded>
<MinValue>0</MinValue>
<MaxValue>1</MaxValue>
<UseNegativeRange>False</UseNegativeRange>
<CanUseNegativeRange>True</CanUseNegativeRange>
</Output>
<Output>
<UniqueID>0904f836-7d7e-4ad8-945c-d561632be26c</UniqueID>
<DefinitionID>00000000-0000-0000-0000-000000000000</DefinitionID>
<DefaultName>Activation 2</DefaultName>
<CustomName>Compensated_Humidity</CustomName>
<IsDisplayed>True</IsDisplayed>
<IsNative>False</IsNative>
<TypeName>Numeric</TypeName>
<IsOutsideConnection>False</IsOutsideConnection>
<IOType>Embrio.NodeEngine.NodeIO.NumericNodeOutput</IOType>
<ShowGraph>True</ShowGraph>
<LinkedIOID>00000000-0000-0000-0000-000000000000</LinkedIOID>
<IsUserAdded>True</IsUserAdded>
<MinValue>0</MinValue>
<MaxValue>1</MaxValue>
<UseNegativeRange>False</UseNegativeRange>
<CanUseNegativeRange>True</CanUseNegativeRange>
</Output>
</Outputs>
</Node>
</Nodes>
EmbrioAdmin  
#7 Posted : Tuesday, April 07, 2015 3:41:56 PM(UTC)
EmbrioAdmin

Rank: Administration

Groups: Administrators
Joined: 12/11/2014(UTC)
Posts: 661

Thanks: 1 times
Was thanked: 36 time(s) in 33 post(s)
Did you have to change the TH02.cpp file to get it to compile? I'm getting errors from that file from the link you sent. If it has any errors they might not show up in the node but in the message log in the bottom right of the application.

I can't get it to compile, but if I could and was getting no output data here are some things I would try:

First try using the built in transform() function on your sensor values instead of dividing by 100.0. To see how, right click on the node and click on the "get help" menu item, then scroll down to the bottom of the help document for a list of built in nodes.

If you're still not getting any data on the outputs, try opening up the serial monitor vial the Arduino IDE at 57600 (remember to close the Embrio connection first). You should be seeing a bunch of lines in the format UPD:5:0.00:0.00, where the 0.00s will be the data being sent over the wire. Once per second you should see a line that says inf:ABCDE where ABCDE will be some random characters. If the data in the UPD lines isn't what's expected, I'd start trying to figure out why it is like that, but I'm guessing it's a problem with your dividing instead of transforming.

If all else fails I finally made the compiled code available, it'll be in your shared data folder, something like: C:\Users\<YourUserName>\AppData\Roaming\Embrio\ArduinoCompile. The code is not super readable or well formatted, but if you get stuck it might help.

Another thing you should do is check the timing on your node. Do that by clicking on the Clock icon in the tool bar on the bottom left of the screen. Assuming things are compiling and working correctly, a program will upload and you'll get back timing data. Next to the project tree, click on the Profiler tab, then on the Nodes tab. I think you'll see that your node is taking quite a lot of microseconds per update (divide by 1000 for milliseconds), too many for it to update 32 times per seconds. This might not fix your immediate problem, but you will probably have to reduce the refresh rate on that agent to something really low like 1 or 2 or 4.

If you're still stuck, add the exact .h and .cpp files and your project directory to a zip file and send it to me and I'll take a look.

Edited by user Tuesday, April 07, 2015 3:43:54 PM(UTC)  | Reason: Not specified

IngmarGuillaume  
#8 Posted : Wednesday, April 08, 2015 7:19:26 AM(UTC)
IngmarGuillaume

Rank: Member

Groups: BetaUser, Registered
Joined: 4/4/2015(UTC)
Posts: 25

Thanks: 3 times
Was thanked: 1 time(s) in 1 post(s)
No, the TH02 library needs a special I2C library, that's probably the error you got (it's in the descriptive text of the link).

Anyway, it have it almost working, but there either is something wrong with the transform function, or I am missing something. I added a few text debug fields and displayed the recorded values in there with the ToString function. However, the output fields do not display anything, despite the fact that the debug fields DO show the correct values.

Attached, you can find a screenshot, including the code. So what am I doing wrong here?

UserPostedImage
EmbrioAdmin  
#9 Posted : Wednesday, April 08, 2015 7:23:16 AM(UTC)
EmbrioAdmin

Rank: Administration

Groups: Administrators
Joined: 12/11/2014(UTC)
Posts: 661

Thanks: 1 times
Was thanked: 36 time(s) in 33 post(s)
I think you just need to change the last parameter in the transform function from 100.0 to 1.0.

(And I think I need to do something about those graphs on the wider nodes, that looks ugly)
IngmarGuillaume  
#10 Posted : Wednesday, April 08, 2015 7:45:38 AM(UTC)
IngmarGuillaume

Rank: Member

Groups: BetaUser, Registered
Joined: 4/4/2015(UTC)
Posts: 25

Thanks: 3 times
Was thanked: 1 time(s) in 1 post(s)
Worked perfectly (see below).
But what's the point of being able to specify a min-max endrange if you HAVE to use 0.0 to 1.0?
Or is that a bug?

UserPostedImage
EmbrioAdmin  
#11 Posted : Wednesday, April 08, 2015 7:48:23 AM(UTC)
EmbrioAdmin

Rank: Administration

Groups: Administrators
Joined: 12/11/2014(UTC)
Posts: 661

Thanks: 1 times
Was thanked: 36 time(s) in 33 post(s)
Hm... that's an interesting point. If the output has the negative range selected (the - button next to the output), you would have to use -1.0, 1.0 at the end. Maybe I should make an even simpler transform variant where you just put in the start range and it uses the range of the output you are setting.

Glad you got it working!

IngmarGuillaume  
#12 Posted : Thursday, April 09, 2015 12:38:26 AM(UTC)
IngmarGuillaume

Rank: Member

Groups: BetaUser, Registered
Joined: 4/4/2015(UTC)
Posts: 25

Thanks: 3 times
Was thanked: 1 time(s) in 1 post(s)
Why don't you make the Transform function work as explained and have it transform values from one range into another? It's kind of illogical that it doesn't do that.

Anyway, now that I've got the hang of it, I can start playing. I really like this tool.

I noticed a spelling error: Compile and upload the controller to a coNnected arduino. There's another spelling error somewhere, but I can't find it anymore. I'll let you know when I come across it again.

A bug? New version available: doesn't show the changes (blank) and started the download, but never got to completion. Had to manually install version 1.1.6.

Tip: right clicking on the canvas displays the menu, clicking delete then deletes the selected node. It would however be wise to that the right click on a node also selects it first. I have often deleted the wrong node.

Question: how can I assign an icon to a node like the ones in the library have (distance and axis sensors).
EmbrioAdmin  
#13 Posted : Thursday, April 09, 2015 5:02:31 AM(UTC)
EmbrioAdmin

Rank: Administration

Groups: Administrators
Joined: 12/11/2014(UTC)
Posts: 661

Thanks: 1 times
Was thanked: 36 time(s) in 33 post(s)
I'm not sure what you mean, doesn't the transform function work as described? The first parameter is transformed from the range specified by the next two into the range specified by the last two. Am I missing something?

Thanks for the rest of the notes, I'll add them to my to-do list. You can't add an icon to an Arduino node yet in the UI,those were assigned on the web site (which will be available to users soon). I'll add that feature soon.
IngmarGuillaume  
#14 Posted : Thursday, April 09, 2015 9:19:08 AM(UTC)
IngmarGuillaume

Rank: Member

Groups: BetaUser, Registered
Joined: 4/4/2015(UTC)
Posts: 25

Thanks: 3 times
Was thanked: 1 time(s) in 1 post(s)
Well, you said it yourself:

Quote:
I think you just need to change the last parameter in the transform function from 100.0 to 1.0.
.

In my previous code, I wrote:

Quote:
Output_Raw_Humidity = Transform(rh, 0, 1000, 0.0, 100.0) ;


in which I wanted to transform a range of 0-1000 into a range from 0 to 100. That didn't show up in the output field. (It remained 0, no graph, no values, although the text output for debugging did show the correct value).

You then suggested to change it to:

Quote:
Output_Raw_Humidity = Transform(rh, 0, 1000, 0.0, 1.0) ;


so changing the last 100.0 value (max target range) into a 1.0 value (max 1.0 target range), and then the graph and values showed up.

So I guess the Transform function has a flaw in it, because any other value besides 1.0 as the max destination range, does not display the value, nor does it graph in the Node Output.

Edited by user Thursday, April 09, 2015 11:36:20 AM(UTC)  | Reason: added some text

IngmarGuillaume  
#15 Posted : Saturday, April 11, 2015 12:28:40 AM(UTC)
IngmarGuillaume

Rank: Member

Groups: BetaUser, Registered
Joined: 4/4/2015(UTC)
Posts: 25

Thanks: 3 times
Was thanked: 1 time(s) in 1 post(s)
OK, now I think I've got it. ALL in's and out's on ALL nodes work on real values between 0 (or -1) and 1. I was so focused on that I2C I wanted to get working that I hadn't noticed this before.

That's a bit confusing. Why wouldn't you be able to pass a signed or unsigned real or int value from one node to another?

In the light of having to work between 0 and 1, then obviously, yes, you can make simpler Transform function, But I'd prefer it the other way around, being able to work with values not between 0 and 1. I'll post this under the suggestions topic.
EmbrioAdmin  
#16 Posted : Saturday, April 11, 2015 5:08:17 AM(UTC)
EmbrioAdmin

Rank: Administration

Groups: Administrators
Joined: 12/11/2014(UTC)
Posts: 661

Thanks: 1 times
Was thanked: 36 time(s) in 33 post(s)
The reason is the numeric values are "activations", from the "agent based" philosophy of the architecture. Its very loosely based on brains and neurons which are connected in ways where activating and suppressing other neurons is how they do their work. An activation of 0 leaves something off and an activation of 1 turns something on, and in that range the multiplying of values coming into the same input is very clean. Values in that range make sense, but values above it don't. An activation of 4 doesn't really mean anything, so activations are all clamped between 0 (or -1) and 1. I like the simplicity of the only data types being activations and triggers, but you're right some times it is strange when you have a value that you want to be a number but you have to transform it to an activation before using it, and then back to a number. I might end up adding another numeric input/output type if that ends up making things easier and more flexible, but I'm actually a little on the fence about it still. If anything I'll add one more numeric type which would be used similar to the text type, I really don't want to start adding a whole bunch of input/output types for each variant of a number people could want to use, that kind of goes against the idea of the software.
IngmarGuillaume  
#17 Posted : Saturday, April 11, 2015 5:22:12 AM(UTC)
IngmarGuillaume

Rank: Member

Groups: BetaUser, Registered
Joined: 4/4/2015(UTC)
Posts: 25

Thanks: 3 times
Was thanked: 1 time(s) in 1 post(s)
I totally understand. It totally makes sense now that you explained. And maybe you should explain that philosophy on the home page.

And indeed, converting it a string and back is what I actually did to pass it from one node to another. So yes, adding just one type, not graphable, not a trigger, not an activation, but just an analogy to the text field but with a real number, would probably all that a lot of people may need.

Another question: what is the visibility (scope) of variables declared in the declaration code block of a node?
EmbrioAdmin  
#18 Posted : Saturday, April 11, 2015 5:31:57 AM(UTC)
EmbrioAdmin

Rank: Administration

Groups: Administrators
Joined: 12/11/2014(UTC)
Posts: 661

Thanks: 1 times
Was thanked: 36 time(s) in 33 post(s)
I'll add it to the long list. If you do find now that you understand the activation data type that you end up not wanting a number data type any more let me know, or also if you really find a numeric type will be useful.

Code in the deceleration block is scoped to just that node. This is done by finding all of the variables declared in the block, and giving them a unique name and replacing them for all code in that node. That's the reason for the "Variables" list under that block, it shows you what variable names it's picking up on. I left that in to make it easy to see if something you think is a variable isn't being picked up on, but I should probably hide that at some point.

If you define a function in the Declaration block, that's not given a unique name yet. I just noticed that when doing interrupt stuff and declaring interrupt function there. I'll fix that eventually.

The idea is that it's really easy to get simple programs working in Arduino, but then gets hard when you need to put a few examples together into one program. I think it's powerful to be able to put one example program into each node and keep them isolated in Embrio, and use the agent based architecture to build the program up around those example pieces.
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Notification

Icon
Error