GithubHelp home page GithubHelp logo

rickardlindberg / frp-arduino-old Goto Github PK

View Code? Open in Web Editor NEW
1.0 2.0 0.0 721 KB

This repository has moved to https://github.com/frp-arduino/frp-arduino

License: GNU General Public License v3.0

Haskell 68.46% Python 8.26% Shell 2.04% C 21.24%

frp-arduino-old's Introduction

Introduction

We believe that programming the Arduino can be more fun if we don't have to use the C language to program it. We aim to create a new language that allows us to program the Arduino using higher-level constructs. Our mission:

Arduino programming without the hassle of C

The language

The language we create has the following properties:

  • It is based on the functional reactive programming (FRP) paradigm
  • It is implemented as a deeply embedded domain specific language (EDSL) in Haskell
  • It compiles to C code

Lets explore them in more detail.

FRP

This sections introduces FRP and shows how it fits in the domain of programming an Arduino.

The central building block in FRP is a stream. A stream contains values that change over time. Consider an input pin on the Arduino. If we constantly read the value of the pin we will get different values (high or low) over time depending on if a button connected to that pin is pressed or not:

Example input stream.

We could take this stream and assign it to an output pin. Whenever there is a new value on the input stream, that value will be sent to the output pin.

The most common thing we to with streams is to convert the values in some way. It is called map. There is a built in stream called clock that increments an integer at some time interval:

The clock stream.

We can convert this stream to a stream of booleans by mapping the isEven function on it:

The clock stream mapped with the isEven function.

We now have a stream that alternates its boolean value at a time interval. This stream can be connected to an output pin that has a led connected to it to make the led blink.

EDSL

Our language is embedded in the Haskell language. That means that when we write programs in our language, we are actually writing Haskell programs.

However, our programs will not look like standard Haskell because they use custom operators that are more suited to the FRP paradigm.

By hosting our language inside Haskell, as opposed to making up our own custom syntax, we gain a few things:

  • We don't have to write our own parser
  • We can take advantage of Haskell's advanced type system

When we combine our program with the language library, we get an executable that, when run, will produce a C file:

The EDSL workflow.

The executable is a compiler from our EDSL to C.

Compiles to C

In order to make our EDSL execute on the Arduino, we compile it to a C source file which we then turn into avr assembly code by using the avr gcc toolchain.

Examples

In this section we will see what our EDSL looks like and what kinds of programs we can write using it.

Running the examples

Command to compile an example:

./make [name of example]

Command to compile and upload an example to a connected Arduino:

./make [name of example] upload

Before we can run these commands, we need to install a few dependencies:

Haskell should be installed system wide, but Arduino-Makefile should just be copied to the root of this repository.

In order to use Arduino-Makefile, we also need standard build tools like make and gcc, and in particular, the gcc toolchain for avr.

On a Fedora system, we can install all dependencies with the following commands:

yum install haskell-platform
yum install arduino-core
git clone https://github.com/sudar/Arduino-Makefile.git

The arduino-core package depends on the following packages:

  • avr-gcc
  • avr-gcc-c++
  • avr-libc
  • avrdude

Example: Blinking a led

import Arduino.Uno

main = compileProgram $ do

    pin13 =: clock ~> toggle

Lets examine this example line by line:

import Arduino.Uno

This imports functions that allow us to define a program in the EDSL.

main = compileProgram $ do

The main function is the standard main function in Haskell. The compileProgram function has the following type:

compileProgram :: Action a -> IO ()

That means that we can define a set of actions in the do-block that we pass to compileProgram. It takes those actions, builds an internal representation of the program, and then generates C code and writes that to a file.

So what action is defined by the last line in the example?

pin13 =: clock ~> toggle

Let's look at the type for the =: operator:

(=:) :: Output a -> Stream a -> Action ()

It takes an output of a specific type and connects it to a sream of values of the same type.

The type of pin13 reveals that it accepts booleans:

pin13 :: Output Bool

That means that the stream we define on the right hand side has to be a stream of booleans. The stream is created with the following expression:

clock ~> toggle

Let's look at the types of the individual components:

clock :: Stream Int

(~>) :: Stream a -> (Stream a -> Stream b) -> Stream b

toggle :: Stream Int -> Stream Bool

clock is a built in stream that produces incrementing integers at a given time interval.

toggle is a function that converts a stream of integers to a stream of booleans by mapping the isEven function: Even integers are converted to true and odd integers are converted to false.

~> is an operator that takes a stream on the left hand side and a function on the right hand side. The result is a stream that we get by applying the function to the stream on the left hand side.

The resulting stream in the example is a stream of booleans that toggles between true and false values at a specific time interval. When we connect that stream to the pin where the led is connect, the led will blink at a specific time interval.

Example: Blinking two leds

import Arduino.Uno

main = compileProgram $ do

    toggled <- def $ clock ~> toggle

    pin13 =: toggled

    pin12 =: toggled ~> invert

API

Actions

compileProgram

compileProgram :: Action a -> IO ()

(=:)

(=:) :: Output a -> Stream a -> Action ()

Stream operations

(~>)

(~>) :: Stream a -> (Stream a -> Stream b) -> Stream b

toggle

toggle :: Stream Int -> Stream Bool

Expression operators

isEven

isEven :: Expression Int -> Expression Bool

Uno outputs and streams

pin12

pin12 :: DSL.Output Bool

pin13

pin13 :: DSL.Output Bool

clock

clock :: Stream Int

Contributing

The contributors are listed in AUTHORS (add yourself).

We use the C4.1 (Collective Code Construction Contract) process for contributions.

Comments on the process:

A patch MUST compile cleanly and pass project self-tests on at least the principle target platform.

In our case, this means that ./test should run without failure.

License

The Haskell library that implements the language and all examples are free software, distributed under the GNU General Public License, version 3. For more information, see COPYING.

This document

This document (README.md) is automatically generated from the sources in the doc folder by running python doc/generate_readme.py.

frp-arduino-old's People

Contributors

mvcisback avatar rickardlindberg avatar

Stargazers

 avatar

Watchers

 avatar  avatar

frp-arduino-old's Issues

Problem: DAG has C code in it

This was a quick hack to get things working.

Possible solution: Create mini language to express what is today expressed as small C code fragments.

Stream as an Applicative

Hi, I was wondering if it'd be useful to reformulate stream as an Applicative.

Specifically,
(~>) :: Stream a -> (Stream a -> Stream b) -> Stream b is alot like (<*>) :: f (a -> b) -> f a -> f b

In some sense, clock is then:
pure ([0..] :: [Int])

which fits nicely since a clock is really just an enumeration.

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.