Integration of the Nim programming language with Arduino IDE

Hello all,

Recently I have made some contributions to the Nim programming language [1] which allows Nim to target low memory MCU's like the Atmel AVR family.

Nim is a portable, high level, statically typed language that compiles to/through C and or C++. We are at this time able to run Nim without problems on Atmel AVR's using gcc-avr and avr-libc, and now I am looking for a way to make it easier for new users to start using Nim on the Arduino product family.

I am looking for some guidelines on how to extend the Arduino IDE, or use some other means of integration, to allow the usage of the Nim compiler.

The practicalites involve at least:

  • Integrating the Nim compiler into the Arduino installation - should be trivial, as Nim is highly portable and runs on all major operating systems without any dependencies
  • Allowing the user to configure what language to use for their program
  • When targeting Nim, the project source file(s) should be passed to the Nim compiler. Nim will then generate a number of C or C++ files in configurable target directory, and these should then be compiled like any other Arduino project source.

Can anyone give me some tips on how to get me started or point to the relevant documentation to accomplish this?

Thank you,

Zevv

  1. https://nim-lang.org/

You may be able to do this by using build hooks:

You define those in the platform.txt of the hardware package of the boards you want to add Nim support to. You could do this in a platform.local.txt file:

Then that could be copied into any hardware package that you want to add Nim support to.

The other alternative would be to create your own custom hardware package, which is a bit easier for the user to install, but more limiting (it will only support the boards you define in your package), more work to create and maintain.

After looking through the information in the Arduino hardware specification, if you have any questions or problems, let us know and we'll try to help out.

Hello Pert,

Thanks for your pointer, that should get me started. I will get back if any more concrete questions arise.

Btw: do there exist similar projects already that integrate other compiled languages in the arduino IDE?

Thank you,

do there exist similar projects already that integrate other compiled languages in the arduino IDE?

I don't think so.
But also consider that the "Arduino Language" can be also thought of as some pre-processing before using avr-gcc/avr-g++

It's one thing to have a system that takes a program written in the NIM language, generates a C++ file from it and gets the Arduino compiler to turn that into machine code for an Uno or Mega.

However to be really useful for Arduino folks the NIM language would need to have equivalents for all the convenience features that the Arduino system provides. Obvious ones are digitalRead() and analogWrite().

And how would a NIM user make use of existing Arduino libraries? Would his/her mind need to be able to switch between NIM and C++ all the time?

And what about the "foreign" ecosystems (for example for the ESP8266) which have been imported into the Arduino IDE? The ability to use the same instructions on very different platforms is very attractive.

...R

Robin2:
And how would a NIM user make use of existing Arduino libraries? Would his/her mind need to be able to switch between NIM and C++ all the time?

Since Nim compiles to c++, FFI is pretty much trivial - but for the best experience a small Nim library will have to be provided that translates the Arduino API functions to their Nim counterparts. This could probably be generated for the largest part.

Robin2:
And what about the "foreign" ecosystems (for example for the ESP8266) which have been imported into the Arduino IDE? The ability to use the same instructions on very different platforms is very attractive.

With proper integration that should be pretty easy, as Nim is mostly agnostic of the underlying architecture - it just generates C code. If the hardware is abstracted away in the Arduino libraries this should all fall in place.

I have a proof of concept working, screenshot http://zevv.nl/div/hello-nim.png repo at GitHub - zevv/nim-arduino: Trying to get Nim integrated into arduino IDE. It's in the "works for me" state, including one or two hard coded paths.

I hate the implementation as it is now: I created a wrapper tool to do the macro/compilation/linking work, and this program lies to the arduino IDE about what is happening: Arduino thinks it is compiling a single .cpp file, while under the hood the Nim compiles nim to a handful of cpp files, which then in turn get compiled, etc. There is a tiny binding library exporting the bare necessities for das blinkenlights and printing "Hello". I also hijack the complete toolchain settings with platform.local.txt, so it is no longer possible to compile normal Arduino code. This needs a switch somewhere.

I'm open to any comments on how to improve things. I'd prefer communication over Github issues or by e-mail.

I just had a quick look at the NIM website. I am reasonably familiar with Python and C++ (just for the Arduino) and I used to use Ruby before switching to Python. I can also do stuff with Javascript.

Convince me that it would be worthwhile learning NIM!

Perhaps post a NIM version of one of the examples that come with the Arduino IDE. Or if you want a slightly more complex example that many Forum users are familiar with try the second example from Serial Input Basics

...R

Robin2:
I just had a quick look at the NIM website. I am reasonably familiar with Python and C++ (just for the Arduino) and I used to use Ruby before switching to Python. I can also do stuff with Javascript.

Convince me that it would be worthwhile learning NIM!

Very short: Nim gives you the convenience of python combined with the power of C++. But I’m not on a missionary trip - if you feel the tools and languages you are using now fit your needs and provide you everything you might need, there is no need to switch and there is probably nothing I can say to change your mind about that. Feel free to give it a quick look and see if it grabs your attention. If so, go for it. If not, nothing lost!

Robin2:
Perhaps post a NIM version of one of the examples that come with the Arduino IDE. Or if you want a slightly more complex example that many Forum users are familiar with try the second example from Serial Input Basics

Free translation of the serial input basics example 2:

import arduino

var rxbuf: string
var newData: bool

proc recvWithEndMarker() =
 while Serial.available > 0:
   let c = Serial.read().char
   if rxbuf.len < 32:
     rxbuf.add c
   if c == '\n':
     newData = true

proc showNewData() =
 if newData:
   Serial.println "This just in ... "
   Serial.println rxbuf
   newData = false
   rxbuf = ""
   
setup:
 Serial.begin 9600
 Serial.println "<Arduino is ready>"

loop:
 recvWithEndMarker()
 showNewData()

I'm regularly accused of being a crusty old curmudgeon so my reputation won't suffer if I say I can't see any noticeable simplicity in the NIM version compared to the regular C++ version.

I note the line

var rxbuf: string

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

...R

Robin2:
I'm regularly accused of being a crusty old curmudgeon so my reputation won't suffer if I say I can't see any noticeable simplicity in the NIM version compared to the regular C++ version.

I never claimed there was, did I? I was asked for an example snippet, and I gave an example snippet. And how much simplicity can be added (subtracted?) from the original sample anyway? Again: I am not here to convince anybody to use this, I'm here to ask about how to do integration of a 3d party language in the Arduino IDE.

Robin2:
I note the line

var rxbuf: string

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

This does not use the (capital S) String class of the Arduino at all - the 'string' here is a Nim string. It indeed uses heap memory, but since the maximum length is limited to 32, no runaways will happen and this is perfectly safe.

zevv:
It indeed uses heap memory, but since the maximum length is limited to 32, no runaways will happen and this is perfectly safe.

And what happens if the user needs to receive 73 characters?

...R

Then you increase the max size - this is no different from the original Arduino example you pointed me to that also has a maximum buffer size set.

I will now probably abandon this thread as the topic has completely moved away from my original intended subject. Thank you for your input.

zevv:
Then you increase the max size

I didn’t see a variable called max size in your program.

If you are referring to the 32 in the line

if rxbuf.len < 32:

are you saying that the NIM compiler is clever enough to notice that number and set aside a fixed 32 byte array for the received data?

If not, it seems to me you are working with something that is just as dangerous as using the String class.

…R