Message Boards Message Boards

19
|
70979 Views
|
35 Replies
|
30 Total Likes
View groups...
Share
Share this post:

Programming the world with Arduino and Wolfram Language

Posted 11 years ago

Attachments:
POSTED BY: Ian Johnson
35 Replies

enter image description here -- you have earned Featured Contributor Badge enter image description here Your exceptional post has been selected for our editorial column Staff Picks http://wolfr.am/StaffPicks and Your Profile is now distinguished by a Featured Contributor Badge and is displayed on the Featured Contributor Board. Thank you!

POSTED BY: EDITORIAL BOARD

HEllo... Not much esxciting going on between Mathematica and Arduino. Old firmware FIRMATA does not allow to read all the pins from MEGA. Please, reopen and take over the subject or comment .

POSTED BY: Jose Calderon

Yes.. I already posted an issue

For ecample, it does not explain hot to get the Device Properties.

POSTED BY: Jose Calderon

NOW IT WORKED!!!!\ I will check again with your link .. But the Wolfram guide in too confusing.

POSTED BY: Jose Calderon

I'm glad you got it working. And what about the Wolfram guide is too confusing (and I'm assuming by the Wolfram guide you are referring to the documentation page I linked to)?

Ian

POSTED BY: Ian Johnson

sketch to verify everything is ok with the board. At what speed is the Mathematica download running? Does this matter? My Device manager states that arduino receives at 9600 buds.

POSTED BY: Jose Calderon

I think there might have been a problem with the sketch I uploaded. I have modified the sketch, can you try reuploading the sketch?

Additionally, if you have 10.1, you can just use the builtin Arduino functionality (which evolved from this), documented at http://reference.wolfram.com/language/ref/device/Arduino.html

POSTED BY: Ian Johnson

Yes.. I uploaded using the Arduino loader..

POSTED BY: Jose Calderon

And you know that your serial port is "COM3"?

POSTED BY: Ian Johnson

I also use <|11 -> 1> but dod not work either.

enter image description here

enter image description here

POSTED BY: Jose Calderon

Hi again Jose,

So what exactly is not working for you? Have you uploaded the sketch to your Arduino with the Arduino software?

Ian

POSTED BY: Ian Johnson

Programming the World with Arduino and Mathematica

In[2]:= arduinoObject = DeviceOpen["Arduino", "COM3"]

Out[2]= DeviceObject[{"Arduino", 1}]

Where "COM4" is my serial port, replace that with whatever port your Arduino is attached on.
Now for some basic device control, we can use

In[15]:= DeviceWrite[arduinoObject, <|11 -> "HIGH"|>]

Out[15]= <|11 -> "HIGH"|>

In[9]:= <|1 -> 1|>

Out[9]= <|1 -> 1|>

Also tested the LED with the insire 3V power supplied to confirm the LED is ok.

enter image description here

POSTED BY: Jose Calderon

This is a great subject. But a bit advance for new users. May you explain what is the "Arduino firmware" and ho w it differs from a "sketch"?

Also , explain what is a Wolfram package and how it is different from running a standard notebook?

Thank you!

POSTED BY: Jose Calderon

Hi Jose,

The Arduino firmware as I called it in the post is the same thing as a sketch. They are the same.

A Wolfram Language package is a file that contains Wolfram Language code and definitions that is meant to be portable. It is intended that packages contain useful definitions that is to be used multiple times. It is similar to a library file in other programming languages. You load packages with either the function Get or the function Needs. In my post, << is a shorthand notation for Get.

Ian

POSTED BY: Ian Johnson
Posted 10 years ago

Hello Ian, unfortunately my ideas are way beyond the skill I reacht up to now. I will try to hook up an arduino micro or nano first, 32u4 / 328P. Then the due...

The temptation is that DUE is not so limited in pin count as are the small arduinos. And the limitation of 10bit DAC, beiing noisy as it is, diminishes together with 4kHz usable sample rate the use as aquisition device. Due would probably stand out there, so I will try.

For you I found a link that mentiones M3 simulation model as open source, so you could swallow it in Mathematica, and it has morphing technology...

Yours

Andi

POSTED BY: Updating Name
Posted 10 years ago

Hello Ian, thank you for this approach!.

Can I use this with my Arduino DUE board, using the 32bit ARM cortex M3 CPU Atmel AtSam3X8E ? In Arduino, you have to let it download the Board via Boards Manager. DUE has a USB to serial bridge with Atmel ARM ATmega16U2 on board, having its own bootloader. The Sam3X8E also has a built-in USB device. And several Hardware Serial Ports, normally the standard one attached to Serial of 32U4 to get the Program in the chip with normal bootloader and bossac programmer.

I am looking forward for this, because combined with coding from mathematica, one could do an oscilloscope with the 12bit 2MHz 2 ADC's it employs. DAC is also there. And 12 PWMs, etc...

Could you use OpenOCD.org's Debugging features to inject code "live"?

Thanks again

Andi

POSTED BY: Andi Hofma

Hi Andi,

You can most certainly use this software with an Arduino Due, but as you said you will need to install the package inside the Arduino software to support the SAM chip on the Due. And you would interact with the Arduino Due via the serial port you mentioned, going through the 32u4 to the computer. You might be able to figure out some way to use the hardware serial ports on the chip itself with something like an FTDI chip on it, but I'm not entirely sure why you'd want to when there's already a dedicated UART/USB chip on the board itself.

Lastly, I am not familiar with the OpenOCD project enough to say whether or not you can inject features to the code "live", but a cursory glance at the project tells me probably not. It is certainly a doable task to rewrite some section of the flash memory to add code, but the problem is that it would get pretty complicated, and to my knowledge almost all of said code would need to be written in assembly, as the code you would load into the flash would have to be from a .hex file. You might look at the optiboot loader code on github, as the bootloader for Arduinos does basically what you are describing, "live" loading of code on the device. Note that the specific project I linked to doesn't support the Due, so you would have to write your own code for the SAM chip. While live loading of code onto a running arduino without resetting is complicated, I can say that the Arduino driver that is currently in Mathematica 10.1.0 (which only supports the Uno at the moment) does support changing a sketch and re-uploading the new sketch completely from within Mathematica. Take a look at the DeviceConfigure section of the documentation. It's not exactly what you were describing, but it is a lot more convenient than reopening the Arduino software every time you need to change the sketch. We do plan on expanding the builtin functionality to other Arduino boards in the future, but for now it is just the Uno.

Ian

POSTED BY: Ian Johnson

Hi there,

I just wonder whether the link to the firmware has been disabled on purpose or whether it's just me who cannot access it.

Cheers,

Marco

POSTED BY: Marco Thiel

I reattached the file as an attachment to the post. The file had a limited amount of time it was hosted on the server, and I had thought that the official driver would be in the software by the time it had expired, but unfortunately not. It will be a little bit longer before the official driver (which was derived from this work) will be integrated into the product.

Ian

POSTED BY: Ian Johnson

Dear Ian,

thanks a lot! That's great. Fantastic work!

Thanks,

Marco

POSTED BY: Marco Thiel

Hi Ian,

well, the Geiger counter is actually rather simple. Like the Arduino it has an AMTEL chip, which in principle can be programmed. Whenever it detects a decay it sends a zero or a one to the serial, depending on whether the last inter-decay interval was shorter or longer than the previous one. It can send the 0/1 rather fast.

Mathematica listens via the serial. Sometimes, the inter decay event time is longer then 10 s and Mathematica times out; that's easy to detect and can be mended in post-processing. The problem is when two events happen in very quick succession.

In some projects, I actually do what you say and

Either one, you send it a command over serial, it changes something, then waits for another command; or two you send it a command over serial, then it executes some type of small set of commands on its own processor, then returns the result.

but in this case I just listen with Mathematica. There is no two way communication, I believe. When I used SerialIO I got to an update interval of 0.002 which was slightly better than the one I choose in MMA10, at 0.01 - everything else being the same. Mathematica is used to determine the times at which the event has (approximately) happened, up to a precision of the sampling interval.

With a couple of students, we also did try to read a simple Potentiometer as fast as we could - one way communication from the Arduino to MMA10. Do you know what the shortest UpdateInterval/highest ScheduledTask frequency is that MMA10 can handle?

Cheers,

Marco

POSTED BY: Marco Thiel

I am not familiar enough with the inner workings of Mathematica to know exactly what the upper limit is, but I do know that operations handling files, like OpenWrite and Write work much faster than higher level functions. You can see Arnoud's response here for some information on how to do that with a Raspberry Pi, but I'm not sure that would help you if you plan on using a normal computer (i.e. Mac or PC).

What you could try is to have an Arduino connected to your Geiger counter, then that Arduino would be connected to Mathematica. This would require a library known as Software Serial to have the Arduino be able to communicate with two UART (serial devices) simultaneously. Although, if as you said the Geiger counter only sends information, you could have just the receive pin of the Arduino connected to the Geiger Counter, then the transmit pin going to the Computer. Obviously this would require some hardware modification such that you take care of the UART to USB handling without using the onboard ATmega32u4 as the serial to USB converter.

Anyways, with all of that, you can have code on the Arduino listening for the 1's and 0's from the Geiger counter and be able to handle those at just about whatever frequency you like, then once the Arduino determines, hey something changed that is important, it can then send off a command to the computer and you can either send the raw data trough the Arduino to the computer or have the Arduino do some processing on it (as I said I am not familiar with this device, so I don't know what exactly that data looks like or if the Arduino has the capabilities to process it properly).

POSTED BY: Ian Johnson

Hi Ian,

I am not sure where you are currently sitting but Arnoud has such a counter. Anyway, your post is brilliant and I will try to put your code to use in some of my projects as well.

In one of your earlier replies you said that you could go up to 1kHz. Did you actually get there? If you manage a bidirectional communication at that speed that would be quite good.

Cheers, Marco

PS: By the way

arduinoObject = DeviceOpen["Serial", {Quiet[FileNames["tty.usb*", {"/dev"}, Infinity]][[1]], "BaudRate" -> 9600}]

seems to work fine on a Mac and you don't have to actually look anything up in the /dev directory. I found that useful.

POSTED BY: Marco Thiel

I work remotely from Minnesota, but anyways I did somewhat manage to get to 1KHz, but I can't confirm that it was 1KHz, as I don't have an oscilloscope handy, but it appeared to be flickering so fast that it almost seemed steady. I accomplished that by just using

Do[(
DeviceWrite[arduinoObject,<|pinNumber->1|;
Pause[1/2000];
DeviceWrite[arduinoObject,<|pinNumber->0];
Pause[1/2000]),
{1000}]

However when I wrapped that in Timing, it took about seven seconds to evaluate, and the light would flicker as I mentioned for about twoish seconds (again, don't have an oscilloscope handy, so can't confirm the time), then it would flash on and off for about two more seconds, then after that it would stay steady on either on or off, depending on which time I ran it, i.e. sometimes it would end with being on, sometimes it would end with being off. So that leads me to suspect that Mathematica is either doing stuff after sending the commands that takes seven seconds, or that it is getting "confused" with all the serial output such that it doesn't output correctly, on top of being slower than suspected.

Also, thanks for the tip on Mac serial discovery, I may have to integrate that into the FindDevice functionality!

Ian

POSTED BY: Ian Johnson

Hi,

this might be interesting in terms of Arduino's speed:

http://www.dustynrobots.com/robotics/arduino-data-logging-and-speed-test/

http://arduino.cc/en/Reference/AnalogRead

This one is the fastest I could find:

http://forums.adafruit.com/viewtopic.php?f=31&t=30557

which claims about 100kHz sampling rate. And in

http://community.wolfram.com/groups/-/m/t/250923

I had trouble getting even close to that. The decay can happen very fast and I need a sampling rate that is as high as possible.

Cheers,

Marco

POSTED BY: Marco Thiel

While I'm not familiar with how the Gieger counter mentioned in your post works, it looks like it is doing one of two things. Either one, you send it a command over serial, it changes something, then waits for another command; or two you send it a command over serial, then it executes some type of small set of commands on its own processor, then returns the result.

As I mentioned above, the first method of having Mathematica and your computer do the legwork in determining what command to run when is very ineffective at high frequencies. Instead, having the Atmel chip on the Arduino execute things is much more effective, as there is no other processes to slow it down, i.e. serial communication, OS processes, etc. If one needs high frequencies I would say that having the Atmel chip on the Arduino execute those commands is the way to go. I would also say that any faster than the theoretical limit mentioned on the documentation page for analogRead would probably require special hardware, and then another driver developed for it, but it is certainly possible to have the Arduino execute some command at that frequency, then pump out the result (or an array of the results) over serial would be the best way to move forward.

In short, serial communication and Mathematica are definitely the bottlenecks for doing things quickly.

POSTED BY: Ian Johnson

Very nice! I'd like to be able to create a GUI with mathematica to control our microscope lasers via the Arduino. This seems like a very good start. Just tested and it works on my system (Windows). However, any thoughts on how fast this can pulse the LED? I tried setting the time delay to 1 ms and it seemed a bit off. How fast can we pulse?

Well, when I built the drivers I used 19200 as the baud rate, which is quite slow for serious applications. It is definitely possible to increase the speed (in both the Mathematica driver file and the Arduino firmware) to 115200, which is the fastest I have seen with an Arduino. However, I would be surprised if it would ever be possible to have something akin to

Do[(DeviceWrite[aruidnoObject,<|pinNumber->1|>];Pause[1/10000];DeviceWrite[arduinoObject,<|pinNumber->0|>;Pause[1/10000]),{5}]

work faster than about 1 KHz, because the front end combined with all of the necessary Mathematica functions to write over serial, etc. add up pretty quickly and the timing becomes problematic.

Instead, I am currently developing a new functionality (using DeviceExecute), which would basically send one command over Serial to the Arduino, which would then cause the Arduino to run some pre-uploaded code (in C/C++), at which point there would be absolutely no problem doing things on the order of microseconds.

This is not yet available because what I plan to do is be able to write whatever commands you want the Arduino to be able to execute in Mathemetica using Symbolic C, then have Mathematica automatically update the firmware file, and then automatically upload the firmware to the chip, all without ever leaving Mathematica. I haven't quite gotten that far, but the most difficult task to me would seem to be the Symbolic C portion of it and the updating of the firmware, as I have accomplished just about all the other tasks.

Also, if you would like to change the baud rate on your drivers, you can do so by opening up the package in Mathematica, and right underneath Begin["Private"] is the definition for open[], which opens the Serial Port. Here, you can change the option from "BaudRate"->19200 to "BaudRate"->115200.

Changing the Baudrate in the Arduino firmware file, you can open up the file, and down a ways is the void Setup() loop. The second to last line here is Serial.begin(19200). Just change it to Serial.begin(115200), and re-upload it and you should be good to go. I tried this, and it seemed to have about 1 KHz frequency, but stopped flashing after a second or two and stayed on, so it's possible that the Arduino runs it fine, but after it finishes Mathematica takes a couple of seconds to catch up.

POSTED BY: Ian Johnson

Thanks for the suggestion, I attached a notebook, which is just basically the original post in notebook form.

POSTED BY: Ian Johnson

This is great - it is nice to have this all in one notebook. But I actually meant ArduinoDriver.m file that is currently linked to webpage with an expiration date. That file won't be accessible after some time. If you wish to attach it - your original post can take many attachments.

POSTED BY: Sam Carrettie

Ian, when using your wonderful Arduino Driver with an Arduino Micro I find that serialBufferRead, at odd times, does not contain the full data array upon which or also unrelated to this occurrence the notebook looses connection to arduinoObject. Is it advisable to include a second If statement in ArduinoRead[pin_] which checks for the Length of serialBufferRead ? I am using OS X 10.9.5 . I include a notebook with results. Thank you in advance, Hanspeter

Attachments:
POSTED BY: Hanspeter Helm

Hi, I have been looking into this, and I think the problem here is that too many requests are being sent to the Arduino, and the Arduino Micro chip doesn't have an additional chip for processing incoming Serial bytes, so I would say that it is possibly the cause of losing the connection, but is still quite wierd. I have an Arduino Micro chip here, and I can't seem to reproduce the disconnection, so it could be unrelated or something in the driver code I'm not seeing.

On the topic of ArduinoRead, I can almost guarantee that the problem is because too many requests are being sent to the Arduino, and Mathematica reads the serial buffer too fast, so it doesn't get a chance to become populated. As you mentioned a check for the length of serialReadBuffer[] would probably solve at least some of the problems, but the other problem is that because so many requests are being sent into the serial buffer on the Arduino, the entirety of the buffer can be overwritten in the time it takes to process an analogRead, as analogRead's are somewhat slow on the Arduino, mainly because the buffer is only 64 bytes. This is why my error values of "qqqq" are showing up, because the original bytes were overwritten, and now there are new bytes there that cause undefined behavior.

If you are curious, you can look into increasing the size of the Serial buffer on the arduino here. That refers to modifying the builtin arduino library that defines the size of the serial buffer to 256 in that case for the Arduino Uno, but it can be easily modified for a Micro. That will probably help out quite a bit with the "qqqq" showing up, but my main recommendation is to put a Pause in between the DeviceReads, something not less than 1/2000 seconds I think should be enough.

Ian

POSTED BY: Ian Johnson

Thank you Ian for looking into my problem. With a pause the error rate is significantly lower (almost perfect). I find that the error which I reported appears ALWAYS, when the Arduino Serial Monitor pop-up window is open at the time the Mathematica program is running, but this is not surprising.

I have a second question though: Why do commands like
DeviceConfigure[arduinoObject,<|"A5"->"analogInput"|>] or DeviceConfigure[arduinoObject,<|6->"digitalInput"|>] trigger a continuously repeated transmission of the serial buffer from the Arduino Micro, rather than enable a single transmission once a DeviceRead statement is sent ?

Thanking in advance,

Hanspeter

POSTED BY: Hanspeter Helm

I'm glad that helped!

And the reasoning I had for putting the device into an always reporting mode is that once one read is triggered, it's likely that more reads are going to be expected, so that was a way to help performance with something like

Dynamic[DeviceRead["Arduino",2]]

or something similar. In the version of the driver that will be released with Mathematica soon, this has changed so that one request provides one response, rather than putting the Arduino into an always reporting cycle.

POSTED BY: Ian Johnson

Ian, this is an excellent post - thanks so much for sharing! Wolfram Community allows file uploads. I think you should attach whatever complimentary to your project files you have - to the actual post. Just click edit on your post and than attach the files. Again, thank you for great material and detailed project description.

POSTED BY: Sam Carrettie
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract