message:
Passing reference to hardware between methods in custom class

I'm a C++ / Arduino newbie, trying to build a custom library for the first time. I created a unit called `CDSensors.cpp`, which has two methods, `SetupSensor` and `ReadSensors`. The sensor is a SparkFun accelerometer/magnetometer.

If there are any errors in the settings, the sensor returns all zeros for compass and accelerometer. If there is no pointer or other connection between the `SetupSensor` and `ReadSensor` methods, the sensor returns all zeros as if it hasn't been setup.

So I'm trying to pass a reference to the sensor library between the methods as shown with the Limu object in the code below. I now get mag data but the accelerometer returns all zeros so something in my object references is messing with the sensor setup? (the accelerometer works ok in the SparkFun demo code, on which my code is based).

Main.ino

    #include <CDSensors.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SparkFunMPU9250-DMP.h>

    CDSensors* LSensors = &CDSensors     (0);
    CDSerialPrint* LSerialPrint = &CDSerialPrint (0);
    MPU9250_DMP Limu = MPU9250_DMP ();
    unsigned long LTimeNow = 0;

    struct meas {
      int BUx;
      int acc_x
    };

    struct meas r;

    void setup() {
      LSensors->SetupSensors (Limu);
    }

    void loop() {
      LSensors->ReadSensors  (Limu, LTimeNow, r.BUx, r.acc_x);
      Serial.print((int) (r.BUx) );
      Serial.print((int) (r.acc_x) );
    }

CDSensors.h

 #ifndef CDSensors_h_h
 #define CDSensors_h
 #include <Wire.h>
 #include <SPI.h>
 #include <SparkFunMPU9250-DMP.h>

 class CDSensors {
   public:
  CDSensors(int);
  static void SetupSensors(MPU9250_DMP *imu);
  void ReadSensors (MPU9250_DMP *imu, unsigned long& TimeNow, int&     BUx,int& BUy,int& BUz,int& acc_x,int& acc_y,int& acc_z,int& a0,int& a1,int& a2,int& a3 );
   private:
  int value;
 };
 #endif

CDSensors.cpp

    #include <Wire.h>
    #include <SPI.h>
    #include <SparkFunMPU9250-DMP.h>
    #include "CDSensors.h"

    //MPU9250_DMP imu;
    boolean       MPU9250_found = false;
    unsigned long TimeNow = 0;
    CDSensors::CDSensors(int givenValue) {
      value = givenValue;
    }

    static void CDSensors::SetupSensors(MPU9250_DMP imu) {
      if (imu.begin() != INV_SUCCESS) {
        while (1) {
          Serial.println("No MPU-9250 found, Check connections");
          delay(5000);
        }
      }
      imu.setSensors(INV_XYZ_ACCEL | INV_XYZ_GYRO | INV_XYZ_COMPASS);
      imu.setGyroFSR(2000);
      imu.setAccelFSR(2);
      imu.setLPF(188);
      imu.setSampleRate(100);
      imu.setCompassSampleRate(100);
    }

    void CDSensors::ReadSensors(MPU9250_DMP imu, unsigned long& TimeNow, int& BUx, int& acc_x) {
      TimeNow = millis();
      if (imu.dataReady()) {
        imu.update(UPDATE_ACCEL | UPDATE_GYRO | UPDATE_COMPASS);
      }
      BUx = imu.calcMag(imu.mx);
      acc_x = imu.calcAccel(imu.ax);
    }

body:
I don't think you are creating instances of these classes correctly. Instead of:

    CDSensors*     LSensors      = &CDSensors     (0);
    CDSerialPrint* LSerialPrint  = &CDSerialPrint (0);
    MPU9250_DMP   Limu = MPU9250_DMP ();

How about:

    CDSensors LSensors (0);
    CDSerialPrint LSerialPrint (0);
    MPU9250_DMP Limu;

I can't get your code to compile, but what I suggest looks a lot simpler.

---

Is your intention here:

    if (imu.begin() != INV_SUCCESS)
      imu.setSensors(INV_XYZ_ACCEL | INV_XYZ_GYRO | INV_XYZ_COMPASS);
      imu.setGyroFSR(2000);
      imu.setAccelFSR(2);
      imu.setLPF(188);
      imu.setSampleRate(100);
      imu.setCompassSampleRate(100);

.. to really be:

    if (imu.begin() != INV_SUCCESS)
      {
      imu.setSensors(INV_XYZ_ACCEL | INV_XYZ_GYRO | INV_XYZ_COMPASS);
      imu.setGyroFSR(2000);
      imu.setAccelFSR(2);
      imu.setLPF(188);
      imu.setSampleRate(100);
      imu.setCompassSampleRate(100);
      }

The indentation suggests so.

---

> if I understood correctly the class is created on startup with
>
>            CDSensors* LSensors = &CDSensors (0);
>
>  and is then persistent.

 `LSensors` is a persistent *pointer* but `CDSensors (0)` is a temporary object created for the purpose of doing an assignment. For example:

    int foo = 2 + 3;

Now the compiler calculates 2 + 3 (giving 5), assigns that to foo, and then discards the temporarily-calculated 5 used to do the assignment.

In your case `CDSensors (0)` calls the constructor for CDSensors, creating a temporary object. Then the "&" operator takes its address (somewhere on the stack I would guess). This address is copied into LSensors. Then the object is destroyed because its lifetime is over. The compiler even warns you this is happening:

     CDSensors*     LSensors      = &CDSensors     (0);
                                                     ^
    sketch_may07a:5: error: taking address of temporary [-fpermissive]

That means the pointer is now invalid because the underlying object (that it is pointing to) has now been discarded.

---

I've even seen people do something like this quite a bit:

         CDSensors LSensors = CDSensors (0);

This isn't so bad because pointers aren't involved, but it still involves making a temporary instance of the class, then *copying* that into LSensors, and discarding the original one.

*This* is how to make a new instance of a class:

     CDSensors LSensors (0);   // the actual class, not a pointer

Or if you want a pointer:

     CDSensors * pLSensors;  // a pointer to the class (initially NULL)

Then in `setup` you create the instance:

    pLSensors = new CDSensors (0);


sender: user

message:
Arduino Libraries: Declaring variables as public?

How come I never see any Arduino Library expose some of it's internal variables as public in the header file? I only see functions which are declared as public, while every variable is declared private.

Background: I want to write my first Arduino library. And I thought of making some variables of this library public, so that I don't have to call a function later on when I import the library.

E.g. I want:

    #include MyLibrary
    ...
    MyLibrary instance();
    instance.avariable = 12345;
instead of:

    #include MyLibrary
    ...
    MyLibrary instance();
    instance.setVariable(12345);

sender: assistant

body:
Classes are used to hide away the complexity of a certain task. The user of the class should not worry about how the library exactly works in the inside, but instead only worry about how it should be used. In many cases directly writing to a member variable can be not only convenient, but hurtful if a wrong value is set. If you instead use a function to set the variable, the author can add code to prevent wrong values from actually being written to the variable. Also there might be some other logic involved, that is not triggered, if you write directly to the variable. So - for the ease of use - the users might want the library to be responsible for this, not themselves.

If you write a library, you have thought about how it should be used. Hiding other ways away is a common way of leading the user through the usage. Ways of usage, that don't go along with the purpose of the library can be hided away to make the correct way clearer. A manufacturer of a saw doesn't give the user instructions how to use the wrong side of the blade, because it doesn't help you with sawing.

This does not mean, that you shouldn't make variables public at all, but only if it makes sense. For example: If you are defining a class, that just represents a point in a coordinate system without hooks to other code, it is totally OK to make the coordinates public. But if you defined the class, so that the point is directly shown on a display, you might want to change the position on the display, whenever one of the coordinates is changed. In this case you can use a set-function to trigger the display update, when a new value was given for the variable.


body:
The Arduino ecosystem is meant mostly for beginners. This often means that people with very little knowledge will be using it and will often try random things to make stuff work. (and once they found something that works will teach it to the next guy that has the dame problem).

Disallowing things that would easily break the invariants of the library from the outset reduces the amount of support you need to give to people that inadvertently break the library by randomly changing some variable.


message:
Arduino: load variables with values read from SD card

I am having a bit of trouble loading values stored on an SD card and assigning them to variables within my program. I can achieve this as one big block of data, but would much prefer them to be saved to variables whilst in a loop or some other process.

My txt file has the following 6 ints & floats values, which are displayed vertically in the file:

2
0.003200
312
1
0.720000
8

Each of these values I want assigned to variables data1,....2,3,4,5,6. Unfortunately, the code I use below will never achieve this, but I am clueless as to any theory to solve this problem. Thanks in advance.

    myFile = SD.open("test.txt", FILE_READ);
        if (myFile) {
        while (myFile.available()) {
            data = myFile.read();
        }
    myFile.close();
    }
    else {
        Serial.println("Read Error");
    }

body:
File implements [Stream][1] just like Serial. so you can use parseInt and parseFloat

    int n = File.parseInt();
    float x = File.parseFloat();
    Serial.println(n);
    Serial.println(x, 6);

  [1]: http://arduino.cc/reference/en/language/functions/communication/stream


message:
Problem connecting Android app to Arduino

Sorry for doing this, I really don't know where to post beacuse this is both Android Studio code and Arduino code so I've posted to both sites.

I want to create a project of using controlling pan-tilt (2 servos combined) using the accelerometer and gyroscope data in smartphone. Creating Android app and sending the accelerometer and gryroscope data to Arduino so that the pan-tilt can determine its location.

My problem is when I connect the Android app to Arduino, no data is shown in serial monitor of Arduino and the pan-tilt is not locating the smartphone.
Please help me to solve this problem.

This *MainActivity* is the class to identify the data of accelerometer and gyrscope.

MainActivity:

    public class MainActivity extends AppCompatActivity implements SensorEventListener{

        private final String TAG = "MainActivity";//log our activity

        SensorManager sm;//define sensor manager
        Sensor accelerometer, gyrometer;//define accelerometer

        TextView xValue, yValue, zValue, xGyroValue, yGyroValue, zGyroValue;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            xValue = (TextView)findViewById(R.id.xValue);
            yValue = (TextView)findViewById(R.id.yValue);
            zValue = (TextView)findViewById(R.id.zValue);

            xGyroValue = (TextView)findViewById(R.id.xGyroValue);
            yGyroValue = (TextView)findViewById(R.id.yGyroValue);
            zGyroValue = (TextView)findViewById(R.id.zGyroValue);

            Log.d(TAG, "onCreate: Initializing Sensor Services");

            sm =(SensorManager) getSystemService(Context.SENSOR_SERVICE);//permission to use the sensor

            accelerometer = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            if (accelerometer != null) {

                sm.registerListener(MainActivity.this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
                Log.d(TAG, "onCreate: Registered accelerometer listerner");
            }else {

                xValue.setText("accelerometer is not supported");
                yValue.setText("accelerometer is not supported");
                zValue.setText("accelerometer is not supported");
            }
            gyrometer = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
            if (gyrometer != null) {

                sm.registerListener(MainActivity.this, gyrometer, SensorManager.SENSOR_DELAY_NORMAL);
                Log.d(TAG, "onCreate: Registered gyrometer listerner");
            }else {

                xGyroValue.setText("gyrometer is not supported");
                yGyroValue.setText("gyrometer is not supported");
                zGyroValue.setText("gyrometer is not supported");
            }
        }

        public void connect(View v){

            DataSender dataSender = new DataSender();
            dataSender.execute((String) xValue.getText(), toString());
            dataSender.execute((String) yValue.getText(), toString());
            dataSender.execute((String) zValue.getText(), toString());
            dataSender.execute((String) xGyroValue.getText(), toString());
            dataSender.execute((String) yGyroValue.getText(), toString());
            dataSender.execute((String) zGyroValue.getText(), toString());

        }

        @Override
        public void onSensorChanged(SensorEvent sensorEvent) {
            Sensor sensor = sensorEvent.sensor;
            if(sensor.getType() == Sensor.TYPE_ACCELEROMETER){

                Log.d(TAG, "onSensorChanged: X: " + sensorEvent.values[0] + "Y: " + sensorEvent.values[1] + "Z:" + sensorEvent.values[2]);

                xValue.setText("xValue:   " + sensorEvent.values[0]);
                yValue.setText("yValue:   " + sensorEvent.values[1]);
                zValue.setText("zValue:   " + sensorEvent.values[2]);
            }else if (sensor.getType() == Sensor.TYPE_GYROSCOPE){

                xGyroValue.setText("xGyroValue:   " + sensorEvent.values[0]);
                yGyroValue.setText("yGyroValue:   " + sensorEvent.values[1]);
                zGyroValue.setText("zGyroValue:   " + sensorEvent.values[2]);

            }

        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }
    }

This DataSender is the class for sending the data to Arduino.

DataSender:

    public class DataSender extends AsyncTask<String, Void, Void> {

        Socket s;
        DataOutputStream dos;
        PrintWriter pw;

        @Override
        protected Void doInBackground(String... voids) {

            String data = voids[0];

            try {
                s = new Socket("192.168.1.100",80);
                pw = new PrintWriter(s.getOutputStream());
                pw.write(data);
                pw.flush();
                pw.close();
                s.close();

            } catch (IOException e){
                e.printStackTrace();
            }

            return null;
        }
    }

This is code that are uploaded in wifi module (esp8266-01) that are connected in Arduino.

Arduino code:

    #include <SoftwareSerial.h>
    #include <Servo.h>

    #define DEBUG true

    SoftwareSerial esp8266(10, 11); // RX, TX

    char tiltChannel=0, panChannel=1;

    //These are the objects for each servo.
    Servo servoTilt, servoPan;

    //This is a character that will hold data from the Serial port.
    char serialChar=0;

    // Center servos
    int tiltVal = 90;
    int panVal =90;

    //smaartphone value
    String inText;
    float value0, value1, value2;

    void setup() { // Open serial communications and wait for port to open:

      servoTilt.attach(2);  //The Tilt servo is attached to pin 2.
      servoPan.attach(3);   //The Pan servo is attached to pin 3.
      servoTilt.write(90);  //Initially put the servos both
      servoPan.write(90);      //at 90 degress.

      Serial.begin(9600); //for monitoring purposes
      esp8266.begin(9600);

      //sendCommand("AT+CIFS+RST\r\n", 2000, DEBUG); // reset module
      sendCommand("AT+IPR=9600\r\n", 1000, DEBUG);
      sendCommand("AT+CWMODE=1\r\n", 1000, DEBUG); // configure as access point
      sendCommand("AT+CWJAP=\"EceConnect\",\"1234\"\r\n", 3000, DEBUG); //connec to
    a network with name EceConnect with password 1234
      delay(1000);
      sendCommand("AT+CIFSR\r\n", 1000, DEBUG); // get ip address
      sendCommand("AT+CIPSTA=\"192.168.1.100\"\r\n", 1000, DEBUG);
      sendCommand("AT+CIPMUX=1\r\n", 1000, DEBUG); // configure for multiple
    connections
      sendCommand("AT+CIPSERVER=1,80\r\n", 1000, DEBUG); // turn on server on port
    80
      Serial.println("Server Ready");

      Serial.println("Android Sensor Type No: ");
      Serial.println("1- ACCELEROMETER  (m/s^2 - X,Y,Z)");
      Serial.println("2- GYROSCOPE (rad/s - X,Y,Z)");
      Serial.flush();

    }

    void loop() { // run over and over

      Serial.flush();
      int inCommand = 0;
      int sensorType = 0;
      unsigned long logCount = 0L;

      if (Serial.available() < 1) return; // if serial empty, return to loop().

        char getChar = ' ';
        if (esp8266.available()) {
          if (esp8266.find("+IPD,0,")) {
            delay(10);
            esp8266.find(":");
            delay(10);
            char letter = esp8266.read();
            Serial.print(letter); //for monitoring purposes
            //Gets the value/char from android app
          }
        }

        // parse incoming command start flag

        if (getChar != serialChar) return; // if no command start flag, return to
    loop().

        // parse incoming pin# and value
        sensorType = Serial.parseInt(); // read sensor typr
        logCount = Serial.parseInt();  // read total logged sensor readings
        value0 = Serial.parseFloat();  // 1st sensor value
        value1 = Serial.parseFloat();  // 2rd sensor value if exists
        value2 = Serial.parseFloat();  // 3rd sensor value if exists

        // send smartphone readings to serial monitor/terminal
        if (DEBUG) {
          Serial.print("Sensor type: ");
          Serial.println(sensorType);
          Serial.print("Sensor log#: ");
          Serial.println(logCount);
          Serial.print("Val[0]: ");
          Serial.println(value0);
          Serial.print("Val[1]: ");
          Serial.println(value1);
          Serial.print("Val[2]: ");
          Serial.println(value2);
          Serial.println("-----------------------");
          delay(10);
        }

        // Check sensor type. If not for  Accelerometer (#1) then ignore readings
        // sensorType 1 is the Accelerometer sensor

      if (sensorType !=1) return;

      panVal = value0; // value0 = X sensor reading
      tiltVal = value1;  // value1 = Y sensor reading

      tiltVal = map(tiltVal, 10, -10, 0, 179);   // Map Accelerometer Y value to
    tilt servo angle.
      servoTilt.write(tiltVal);
      delay(10);

      panVal = map(panVal, -10, 10, 0, 179);  // Map Accelerometer X value to pan
    servo angle.
      servoPan.write(panVal);
      delay(10);
    }

    String sendCommand(String command, const int timeout, boolean debug) {
      String response = "";
      esp8266.print(command); // send the read character to the esp8266
      long int time = millis();
      while ((time + timeout) > millis()) {
        while (esp8266.available()) {
          // The esp has data so display its output to the serial window
          char c = esp8266.read(); // read the next character.
          response += c;
        }
      }

      if (debug) {
        Serial.print(response);
      }
      return response;
    }

body:
In the `loop` function you have a line

    If (Serial.available() < 1) return;

This prevents further code to be processed if there is nothing in the hardware serial buffer. Think about that.


message:
compare two hex files

I need to check if the code burned on the some Arduino is the same one as I have.
I know how to get the hex file from the Arduino. My question is what influence the hex code? Board Type? Microprocessor type? avrdude version? anything else?

body:
The lines in a typical hex file include a VLI (variable length indicator). The hex files output from the IDE might have different lengths than those produced by avrdude. As a simple example:

File 1:

    03ABC
    03DEF

File 2:

    06ABCDEF

Those files will compare differently to each other but convey the same information, split differently between lines.

To do a genuine comparison you would need to account for that.

> Board Type?

Different boards, but with the same processor, might have identical files.

> Microprocessor type?

Different processor would almost certainly have different hex files.

> avrdude version?

Probably not, however see my comments above about the VLIs.

> anything else?

As I said, the compiler may generate lines with (say) 16 bytes per line, but avrdude might read back lines with 32 bytes per line. Thus they would look different but convey the same hex codes, once you allow for that.


message:
Sound localization using two mics, Arduino Uno on MATLAB

I have been trying to achieve this for a long time using the ITD method and have gone through various articles on the net.

I want to know if its possible to actually achieve sound localization using an Arduino Uno and two MEMS mics with a high gain (https://www.sparkfun.com/products/9868).

I have been trying this on MATLAB using the a=arduino() command and readVoltage command but the main issue I face is that for a particular sound (clapping for instance) the time difference between the two mics is not always the same which results in different direction predictions.

We managed to increase the low resolution of the Arduino by removing unnecessary operations. Now we are able to get an array of size 750 for 10 secs giving a resolution of 0.01 secs. I am not sure if that is enough.

I basically have 3 arrays, one storing the sampling times, and the other two storing the amplitudes of the two analog inputs at that particular time in the first array.

Now I look for a peak in one and then the corresponding near peak in the second one and then compute the time difference. After this I can compute the angle using the speed of sound and the distance between the mics.

Please let me know how I can make this work or where I am going wrong.

body:
Let's assume a microphone distance of 0.5m (which may be just small enough for you). Sound travels with about 300m/s in normal conditions. Let's also say, that you want at least a precision in the angle measurement of 15°.

As stated in the project Mikael linked, it is important that the distance to the sound source is big enough (so that the waves can be seen as planar). Then you have the following situation:
[![enter image description here][1]][1]

We are interested in the difference in distance, that the waves have to travel to the two microphones. It can be calculated by `delta s = d * sin(alpha)`. With `15°` we get `delta s = 0.13m`. The time difference is calculated by `delta t = delta s/v`, where `v` is the speed of sound. We get `delta t = 0.43ms` which equates to `2.32kHz` sampling frequency. Since we use two microphones that must be sampled sequentially, the sampling frequency must be doubled. In the end we have a sampling frequency of `4.64kHz`. So your sampling time of `0.01s` wouldn't be enough for that.

The largest time difference in this setup (with the sound source in line with the microphones) would be `1.6ms`, so your sampling time would be too big even for this.

Regarding the transmission with a baudrate of say 115200 baud this shouldn't be a problem.

But the actual speed of your setup highly depends on your code, which you haven't shown. Maybe [this forum post][2] can help you going further.

  [1]: https://i.stack.imgur.com/QBtzN.png
  [2]: http://forum.arduino.cc/index.php/topic,6549.0.html


body:
You should use the Arduino interrupt function.
This will get it to 4 micros. You cannot use delay on Arduino counting in micros that is needed.
You can have ca 10 cm between mics doing as follows:

You may use accelerometer instead of mic.
Serial read, don't work, too slow. Use ISR..together with Arduino clock is 16 MHz.
Gives a error in +- 10 micros.
Given that it's possible to get the angle within 0.5 degrees if using Sine/Cosine. But, the trigg appear at different places on the waves sinus, giving you extra errors at low freq.

Don't give up.  This works:

1. Attach interrupt (ISR) on 2 pins. Make all variable used in ISR volatile.
2. Use internal clock with micros() to stop at interrupt, flag a variable true if rising/falling/change.
3. Use the time difference from trigs for calculations.
4. Calculations do in loop, not ISR calculate using radians.
5. Don't try to read or write anything while in ISR or before calculations, that mess up the clock!
6. Use 11500 baudrate.
7. If in loop or ISR = true then disable interrupt by state variable.


message:
Arduino variables loaded from SD card

I am trying to load some variables from an SD card on the start up of my arduino Uno. I have been given some advice but am unable to communicate at the same hours. Using this advice, I have the following edited code, but it doesn't work and I believe that it's my implementation that is the problem. All help would be greatly appreciated.

    myFile = SD.open("test.txt", FILE_READ);
        if (myFile) {
            while (myFile.available()) {
                myFile.read();

                km = myFile.parseInt();
                kmTemp = myFile.parseFloat();
                kmrevs = myFile.parseInt();
                miles = myFile.parseInt();
                milesTemp = myFile.parseFloat();
                milesrevs = myFile.parseInt();

                }
            myFile.close();
            }
        else {
            Serial.println("Read Error");
        }

body:
in you [previous question][1], where I answered, you had no commas or new-lines in the example file content. the parseInt and parseFloat ignores only spaces by default.

remove the commas or read them or ignore them with parseInt parameter SKIP_ALL

    km = myFile.parseInt(SKIP_ALL);

  [1]: https://arduino.stackexchange.com/questions/52480/arduino-load-variables-with-values-read-from-sd-card


message:
Can increasing the size of the software RX buffer cause problem in Arduino Uno

If I were to increase the of the buffer array from 64 to say 512 will this bring any long term problem in the Arduino Uno.

Changing from this:

    #ifndef _SS_MAX_RX_BUFF
    #define _SS_MAX_RX_BUFF 64 // RX buffer size
    #endif

to this:

    #ifndef _SS_MAX_RX_BUFF
    #define _SS_MAX_RX_BUFF 512 // RX buffer size
    #endif

This is the header file of the software serial.

body:
The buffer is in the UNO's limited (2K) RAM; you'd be using 1/4 of it for the input buffer. If your app is small enough and simple enough (limited call depth, specifcally), there may still be enough RAM for your app to run successfully. If you have lots of globals (remember to include libraries when you're considering RAM use), allocate much memory from the heap (with `new` or `malloc()`) or have a complex call structure such that funcA() calls funcB() calls funcC() calls ... (etc) so that many functions' stack-frames remain allocated at once - at any point in your program - your program could suffer a stack-collision: the call-stack descends low enough that it can overwrite, or get over-written by, your heap or global data.

Why do you want so large an input buffer? Will data be coming in a high rate or in large bursts, while processing of the data will be infrequent or occur at irregular times? Given the limited RAM in the UNO, running complex programs on one can require something of a balancing act in how you use resources.

Update:

> i was performing some AT commands with software serial and buffer limitation generated junk value

Other reasons why SoftwareSerial might return bad data are:

 - Using too high a baud rate (9600 baud seems to be about the max);
 - Code that turns the interrupts off too often or for too long;
 - Other devices creating too many interupts (perhaps a built-in timer running at a high rate).

The replies to most devices' AT commands that I know of are short enough to not require a huge receive buffer. Asking for list of WiFi SSIDs from an ESP8266 could generate a large reply but most responses should not overflow a more modest buffer.


body: Most arduino modules have 2k ram. So think about that. Whether you need more buffer or more working space. Keep in mind that other libraries are also using the same ram.


message:
Need help optimizing snake game code for Arduino Nano

Here's the code:

https://pastebin.com/ypWe4NZw

This is the output when I compile:

Sketch uses 13086 bytes (42%) of program storage space. Maximum is 30720 bytes.
Global variables use 1456 bytes (71%) of dynamic memory, leaving 592 bytes for local variables. Maximum is 2048 bytes.

Everything runs smoothly until getNextFood(), Line 194.  I try to make a LinkedList of integers from 0 to 255 (since I am using a 16x16 LED grid).  However, my list only fills up to about 39, then the rest are set to zero.  I suspected that I was out of memory, so I tried optimizing a few things and was able to get to 42.  I changed all the ints to bytes in the getNextFood function and got up to 61, but that broke my program somehow (inf loop).

Any suggestions on how to fix this?  If I can get this list to fit, the program is basically done, I have nothing else to add assuming it works as intended.

Also, why I am running out of RAM in the first place?  Can someone explain which parts of the program are gobbling up those bytes during runtime (because I would expect the integer list to take up around 512 bytes leaving 80 bytes left, so why I am getting cut off around 40 integers or 80 bytes?)

Thanks.

Edit1:  People have pointed out that linked lists take up a lot of space.  I am using this library because the way the program is designed, I needed to make an array that could change size.  I needed to be able to add and remove elements.  Maybe there is a better way to do it, I don't know.  I thought about making a single 16x16 array for the whole thing and using a different number for each type of piece.  I don't know how I would do the snake movement in that case though, because each piece is "connected" to the one in front of it.
If anyone knows of a similar library that would save space I'd be happy to try it.  Also there might be a way for me to avoid using the tempSnake list.

Edit2:  Per Paul's suggestion, I rewrote the code using a single 16x16 array to represent the entire game board, removing the need for LinkedList.  However, it seems I am still falling short, unless there is something else wrong with my code.  The program resets when I try to generate the food tiles.
https://pastebin.com/ZU4hX477

body:
16x16 = 256

So there are 256 possible places to put a piece of snake.
The max length of the snake will be 256 (fill the board completely).

So if we take an array of bytes (0-255) that is 256 bytes long we could completely map the snake.

Every step you move (unless if the snake just ate some food) you put it's head forward one step, and remove the last part.

So if we make the new head the value of "snakeLength" and do each piece of the body -1 every round. We will get this "decaying" effect.

For example:

    [ 6][5][4] (all -1, head down) [ 5][4][3]
    [ 0][0][3]                     [ 6][0][2]
    [ 0][1][2]                     [ 0][0][1]

This probably isn't the most efficient method (especially not if you scale it up), but in this case the logic would be very easy.

If the head collides with a position that is not 0, it'll be game over. For the food/apple you could use an x/y value.

If a space is not 0, do it -1.

The upside of this is that you don't allocate memory runtime and you know exactly how many you use.
This setup should also make it easier for you to avoid "copying" the whole list all the time, you can basically loop through the array and do -1 for all but those who are 0.


message:
Strage delay needed after Serial.read()

I'm using a RedBear Duo to read the Serial writes from a RedBear Nano v2. Basically, I use a digital pin of the Duo to raise an interrupt on the Nano. Once, the nano catches the interrupt it writes on its Serial.

You can find a minimum working example below:

### RedBear Duo

    #include <Wire.h>

    /*BLE and WiFi setup*/
    #if defined(ARDUINO)
    SYSTEM_MODE(MANUAL);
    #endif

    char incomingByte;   // for incoming serial data

    void setup() {
        Serial1.begin(115200);     // opens serial port, sets data rate to 9600 bps
        delay(500);
        Serial1.println("Begin!");
        Serial2.begin(115200);

        pinMode(D5, OUTPUT);
    }

    void readSerial() {
        while (Serial2.available() > 0) {
            incomingByte = Serial2.read();
            Serial1.print(incomingByte);
        }
        Serial1.println(" ");

    }

    void loop() {
        digitalWrite(D5, HIGH);
        readSerial();
        delay(2);     // Here's the delay I'm talking about
        digitalWrite(D5, LOW);
        delay(1000);
    }

### RedBear Nano

    uint8_t fire;
    void task_handle(void) {
        fire = 1;
    }

    void setup() {
        Serial.begin(115200);
        fire = 0;
        pinMode(D4, INPUT);
        attachInterrupt(D4, task_handle, RISING);
    }

    void loop() {
        if (fire == 1) {
            fire = 0;
            Serial.write("hello ");
            // Serial.println("fire");
            digitalWrite(D13, HIGH);
        }
        delay(150);
    }

I found this question (https://electronics.stackexchange.com/questions/28739/arduino-delay-of-1ms-necessary-between-serial-read-and-serial-write), and I understood that the problem might be the fact that it takes a while to empty the Serial buffer.

However, I tried to bring the baudrate at 500000 (more than 3x) and still if I change the delay to delay(1), the code is not printing what it has received on the Serial.

I'm trying to understand what is really going on and why I need this delay(2).

Thanks a lot in advance!

body:
Try this code: first delay produces 1ms pulse on pin D5. Without this delay the pulse could be too short for the nano to catch it (you can use delayUs and try finding the shortest interval that produces reliable result). We know that after this pulse, nano sends some data. So wait 100ms to collect it. If you call readSerial right after the pulse was sent, you won't get anything, because you need to wait at least for single byte transmission

    void loop() {
        digitalWrite(D5, HIGH);
        delay(1);
        digitalWrite(D5, LOW);

        delay(100);
        readSerial();

        delay(1000);
    }


body:
This line is wrong:

    attachInterrupt(D4, task_handle, RISING);

It should be:

    attachInterrupt (digitalPinToInterrupt (4), task_handle, RISING);

In any case, attachInterrupt does not apply to D4, it is for D2 and D3 on the Atmega328P.

Note that the pin number is 4, not D4.


message:
Using an Arduino as a Human Interface Device that sends analog inputs

I would like to have an arduino board act as a human interface device that can send analog inputs like joysticks.

As it currently stands I see two aproaches to this issue:

1. Use the arduino hid library and program all the reports in myself. This should be fairly simple but I can't seem to find any recourses that I actually understand. I get the idea of reports but I dont get how the report format is described to the OS. I also dont understand how drivers on the pc side of things play into this whole equation.

2. Write some software that makes a serial connection with the arduino and uses java's robot functionality (or similar) to controll a joystick, if even possible. This method would be much easier but would feel overall less polished.

Thank you for your help in advance!

body: https://github.com/MHeironimus/ArduinoJoystickLibrary does my first aproach. The limitations one what board it can be will not be an issue because I have an extra 32u4 board.


message:
Serial.read(); and state machine for AT commands

I have a strange type of issue: the index of the array doesn't increment and when I print the value from the *serialdata[pointingfinger]* it just gives me an empty space.
This is a state machine (I guess) that should check what is the current char that's being written into the array and its position to avoid searching it later. When we have a finished line it changes the bigger state machine to another mode (that checks if four chars further is the command) when the processing is done it should get back getting the next line.

This is Arduino Leonardo and Serial is the USB and Serial1 is where I send and receive AT commands.

<!-- language-all: lang-cpp -->

    const long interval = 1000;
 static long currentMillis;

 char plussignpoint = 0; //To determine where is the + in +CCLK in the char array

 char serialdata[256] = ""; //Array to store the chars before parsing

 int rdpos = 0;

 int pointingfinger = 0;

 char timeen = 0;
 byte stat0 = 0;
 char futstat0 = 0;
 char searchcharpos = 0;

 char enabled = 0;

 char searchchartype = 0;

 char smsvalid = 0;

 void setup()
 {
   Serial.begin(9600);
   Serial1.begin(9600);
   Serial1.write("ATE0\r");
 }

 void loop() {
  if (millis() - currentMillis >= interval)
  {
    Serial1.print("AT+CCLK?\r"); //ask for the time

    enabled = 1;

    currentMillis = millis();
  }

  if (enabled == 1) {
    if (stat0 == 0) {
   if (Serial1.available () > 0) {
     pointingfinger++;
     serialdata[pointingfinger] = Serial1.read();
     if (serialdata[pointingfinger] == '+') {

    searchcharpos = pointingfinger;
    searchchartype = 1;
    futstat0 = 1;
     }
     else if (serialdata[pointingfinger] == '$') {
    if (smsvalid = 1) {
      searchcharpos = pointingfinger;
      searchchartype = 2;
      futstat0 = 2;
    }
    if (smsvalid = 0) {
      stat0 = futstat0;
      pointingfinger = 0;
    }
     }
     else if (serialdata[pointingfinger] == '\n') {
    stat0 = futstat0;
    pointingfinger = 0;
    enabled = 0;
     }
     else if (serialdata[pointingfinger] == '\r') {
    stat0 = futstat0;
    pointingfinger = 0;
    enabled = 0;
     }
     else {
    stat0 = 0;
    pointingfinger = 0;
     }
   }

   if (pointingfinger == 255) {
     pointingfinger = 0;
     enabled = 0;
   }

    }
  }
 }

**EDIT:** I forgot to include what AT commands it should parse:

    Arduino: AT+CCLK?

    SIM800H: +CCLK: "04/01/01,01:35:31+00"

             OK

body:
When checking value of `smsvalid` you use assignment operator `=` instead of comparison operator `==`.

                else if (serialdata[pointingfinger] == '$') {
                    if (smsvalid == 1) {
                        searchcharpos = pointingfinger;
                        searchchartype = 2;
                        futstat0 = 2;
                    }
                    if (smsvalid == 0) {
                        stat0 = futstat0;
                        pointingfinger = 0;
                    }
                }

And also you increment `pointingfinget` prior writing to `serialdata` buffer. This means that the first character will be written at index 1. So the first character serialdata will be zero, which means empty string.

          pointingfinger++;
          serialdata[pointingfinger] = Serial1.read();

There are many issues with your code, I pasted your code to [online gdb c++ compiler](https://onlinegdb.com/HJqeGtapf), so you can play with it and see what is going on.

Those AT state machines aren't easy to finetune on Arduino. I spent a lot of time debugging similar code and found out that the best way is to unit test all possible situations in visual studio or xcode. Arduino is just C++ and if you copy/paste some portions of your code to C++ IDE, after implementing few functions or classes it should work. For example, to make your code working in XCode, I had to implement some dummy Serial1 class and simplify the loop code:

    class _Serial1
    {
        std::string buffer{"OK\r\n"};
    public:
        int available()
        {
            return (int)buffer.size();
        }

        char read()
        {
            char c = buffer[0];
            buffer.erase(0, 1);
            return c;
        }
    } Serial1;

    void loop() {
        if (enabled == 1) {
            if (stat0 == 0) {
                if (Serial1.available () > 0) {
                    pointingfinger++;
                    serialdata[pointingfinger] = Serial1.read();
                    if (serialdata[pointingfinger] == '+') {

                        searchcharpos = pointingfinger;
                        searchchartype = 1;
                        futstat0 = 1;
                    }
                    else if (serialdata[pointingfinger] == '$') {
                        if (smsvalid == 1) {  // ==
                            searchcharpos = pointingfinger;
                            searchchartype = 2;
                            futstat0 = 2;
                        }
                        if (smsvalid == 0) { // ==
                            stat0 = futstat0;
                            pointingfinger = 0;
                        }
                    }
                    else if (serialdata[pointingfinger] == '\n') {
                        stat0 = futstat0;
                        pointingfinger = 0;
                        enabled = 0;
                    }
                    else if (serialdata[pointingfinger] == '\r') {
                        stat0 = futstat0;
                        pointingfinger = 0;
                        enabled = 0;
                    }
                    else {
                        stat0 = 0;
                        pointingfinger = 0;
                    }
                }

                if (pointingfinger == 255) {
                    pointingfinger = 0;
                    enabled = 0;
                }

            }
        }
    }

And the compiler immediatelly pointed me at the incorrect assignments and also I was able to debug the code step by step and see what is happening inside.

In my situation I was interfacing SIMCOM900 gprs module and I made a state machine that allows me to write code like this:

    virtual void Program()
    {
        switch (Pc())
        {
            case 0: _ASSERT(strlen(mApn)>0);
                    Stream() << "AT+CSTT=\"" << mApn << "\",\"\",\"\"\r\n";
                    break;
            case 1: Expect("OK\r\n");
                    if (Expect("+CME ERROR")) { Error("CME Error when attaching apn"); Return(false);}
                    if (Timeout(25000)) Return(false);
                break;
            case 2: Stream() << "AT+CIICR\r\n"; break;
            case 3: Expect("OK\r\n");
                    if (Timeout(15000)) Next(); break;
            case 4: Stream() << "AT+CIFSR\r\n"; break;
            case 5: if (ReadIpAddress()) Next();
                    if (Timeout(2000)) Return(false); break; // longer?
            default: Return(true);
        }
    }

Here is a bit older version of it:
https://gist.github.com/gabonator/88b80d9c6b16d699d6f4234ebc3a2587


message:
samd21 linking, change the base addresse from the default

I'm working on creating a safe firmware upgrade for my adafruit feather m0.
I understand from my CTO that wrote the previous upgrade that for either samd21 or all arm m0 (not sure which) the compiler compiles non relative addresses, meaning bx 0x3000 will jump to address 0x3000 and not 0x3000 bytes from my location.
My goal is to split the flash into 4 banks:

 1. bootloader (2k)
 2. user data
 3. firmware #1
 4. firmware #2
which firmware will be booted is up to a flag in the flash do decide.
i understand from my predecessor this is an issue since firmware#2 when loaded to ram might not run.
I disagree and do believe simple changes in the .ld script should accomplish the task.

My only question to  you guys is changing the .ld script .text address is enough ? i know the bootloader jumps to an address that was defined in the  .ld script if it's not 0xFFFFFF (if the flash was written to).
do i ned to change the .ld script to include two .text sections ? do i need to also define how they reside in the RAM as well ?
any examples ? hint ?

Thanks.

body:
A typical LD script consists of two sections - one that defines memory ("MEMORY") regions, and another that defines what to put in those memory regions ("SECTIONS").

To carve holes in an existing memory layout it is usually enough to just change the first section - the part that defines the layout of the memoy. Shrink and move existing blocks of memory and insert new ones.

For example you may have this at the moment:

    MEMORY
    {
      FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
      RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
    }

There is a hole already defined of size 0x2000 at the start of flash, and the sketch is loaded from 0x2000 onwards.

You may want to shrink and move that, and add a "user data" chunk. It's enough to just go:

    MEMORY
    {
      USERDATA (rx) : ORIGIN = 0x2000, LENGTH = 0x1000
      FLASH (rx) : ORIGIN = 0x3000, LENGTH = 0x00040000-0x3000
      RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
    }

(I collapsed some of the maths cus it's pointless).  Now the flash area (where the sketch goes) has been shrunk by 0x1000 and moved an extra 0x1000 up the memory map. A USERDATA chunk has been inserted which you can then use later on if you so wish.

To make things get put in there by the linker script (you don't need to change anything else to move the sketch data...) you can define a new section in the later part of the linker script:

    .userdata :
    {
        KEEP(*(.userdata))
        KEEP(*(.userdata.*))
    } > USERDATA

That should then place anything that you put in a `.userdata` section (or a subsection within that) within your sketch into the USERDATA chunk of flash - separate from your sketch.

    (sketch)
    const uint8_t __attribute__((section(".userdata"), used)) data[] = { 10, 100, 123, 177, 221, 49 };

However, if you plan to use it like EEPROM and only write to it using code in your sketch then you don't need to worry about anything like that - just carve out the hole.  You can also provide some globals to help with your code, though:

    (linker script)
    PROVIDE(userdata_start = ORIGIN(USERDATA))
    PROVIDE(userdata_length = LENGTH(USERDATA))

Then you can use those in your program to know where the USERDATA chunk is and how big it is (ideal if you ever choose to change it - no need to change your code, only the linker script).


message:
Interfacing MPU6050 with Arduino through Simulink S-function

I am interfacing MPU6050 with Arduino using Simulink S-function builder.
I'm implementing [MPU6050_DMP6 code](https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino) in Simulink s-function builder by following [this](https://www.youtube.com/watch?v=PXtXcsiJbGw) video. By following this tutorial I implemented the S-function as:
I set sample time 0.05 in s-function builder block and number of discrete state=1 and sample mode = 1.
in the libraries tab I put the following code:
<!-- language-all: lang-cpp -->

    #include <math.h>
    #ifndef MATLAB_MEX_FILE
    int counter=0;
    #include <Arduino.h>
    #include "I2Cdev.h"
    #include "I2Cdev.cpp"

    #include "helper_3dmath.h"
    #include "MPU6050_6Axis_MotionApps20.h"
    #include "MPU6050.h" // not necessary if using MotionApps include file
    #include "MPU6050.cpp" // not necessary if using MotionApps include file
    // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
    // is used in I2Cdev.h
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        #include "Wire.h"
        #include "Wire.cpp"
        #include "utility/twi.h"
        #include "utility/twi.c"
    #endif
    // class default I2C address is 0x68
    // specific I2C addresses may be passed as a parameter here
    // AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
    // AD0 high = 0x69
    MPU6050 mpu;

    #define OUTPUT_READABLE_YAWPITCHROLL

    // uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration
    // components with gravity removed. This acceleration reference frame is
    // not compensated for orientation, so +X is always +X according to the
    // sensor, just without the effects of gravity. If you want acceleration
    // compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.
    //#define OUTPUT_READABLE_REALACCEL

    // uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration
    // components with gravity removed and adjusted for the world frame of
    // reference (yaw is relative to initial orientation, since no magnetometer
    // is present in this case). Could be quite handy in some cases.
    //#define OUTPUT_READABLE_WORLDACCEL

    // uncomment "OUTPUT_TEAPOT" if you want output that matches the
    // format used for the InvenSense teapot demo
    //#define OUTPUT_TEAPOT

    #define INTERRUPT_PIN 2  // use pin 2 on Arduino Uno & most boards
    #define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
    bool blinkState = false;

    // MPU control/status vars
    bool dmpReady = false;  // set true if DMP init was successful
    uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
    uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
    uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
    uint16_t fifoCount;     // count of all bytes currently in FIFO
    uint8_t fifoBuffer[64]; // FIFO storage buffer

    // orientation/motion vars
    Quaternion q;           // [w, x, y, z]         quaternion container
    VectorInt16 aa;         // [x, y, z]            accel sensor measurements
    VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
    VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
    VectorFloat gravity;    // [x, y, z]            gravity vector
    float euler[3];         // [psi, theta, phi]    Euler angle container
    float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

    // packet structure for InvenSense teapot demo
    uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };

    // ================================================================
    // ===               INTERRUPT DETECTION ROUTINE                ===
    // ================================================================

    volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
    void dmpDataReady() {
        mpuInterrupt = true;
    }
    #endif

in the discrete update tab I have implemented following code:

    if (xD[0]!=1){
    #ifndef MATLAB_MEX_FILE
           // join I2C bus (I2Cdev library doesn't do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
            Wire.begin();
            Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties
        #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
            Fastwire::setup(400, true);
        #endif

        // initialize serial communication
        // (115200 chosen because it is required for Teapot Demo output, but it's
        // really up to you depending on your project)
        Serial2.begin(115200);
    //     while (!Serial); // wait for Leonardo enumeration, others continue immediately

        // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio
        // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to
        // the baud timing being too misaligned with processor ticks. You must use
        // 38400 or slower in these cases, or use some kind of external separate
        // crystal solution for the UART timer.

        // initialize device
        Serial2.println(F("Initializing I2C devices..."));
        mpu.initialize();
        pinMode(INTERRUPT_PIN, INPUT);
        // verify connection
        Serial2.println(F("Testing device connections..."));
        Serial2.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

        // wait for ready
       // Serial2.println(F("\nSend any character to begin DMP programming and demo: "));
       // while (Serial2.available() && Serial2.read()); // empty buffer
       // while (!Serial2.available());                 // wait for data
       // while (Serial2.available() && Serial2.read()); // empty buffer again

        // load and configure the DMP
        Serial2.println(F("Initializing DMP..."));
        devStatus = mpu.dmpInitialize();

        // supply your own gyro offsets here, scaled for min sensitivity
        mpu.setXGyroOffset(220);
        mpu.setYGyroOffset(76);
        mpu.setZGyroOffset(-85);
        mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

        // make sure it worked (returns 0 if so)
        if (devStatus == 0) {
            // turn on the DMP, now that it's ready
            Serial2.println(F("Enabling DMP..."));
            mpu.setDMPEnabled(true);
            // enable Arduino interrupt detection
            Serial2.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
            attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
            mpuIntStatus = mpu.getIntStatus();
            // set our DMP Ready flag so the main loop() function knows it's okay to use it
            Serial2.println(F("DMP ready! Waiting for first interrupt..."));
            dmpReady = true;

            // get expected DMP packet size for later comparison
            packetSize = mpu.dmpGetFIFOPacketSize();
        } else {
            // ERROR!
            // 1 = initial memory load failed
            // 2 = DMP configuration updates failed
            // (if it's going to break, usually the code will be 1)
            Serial2.print(F("DMP Initialization failed (code "));
            Serial2.print(devStatus);
            Serial2.println(F(")"));
        }
        #endif

      xD[0]=1;
     }
and in output tab I have implemented this code:

    if (xD[0]==1){
        #ifndef MATLAB_MEX_FILE
    // if programming failed, don't try to do anything
        if (!dmpReady) {
            return;
        }

        // wait for MPU interrupt or extra packet(s) available
        while (!mpuInterrupt && fifoCount < packetSize) {
            // other program behavior stuff here
            // .
            // .
            // .
            // if you are really paranoid you can frequently test in between other
            // stuff to see if mpuInterrupt is true, and if so, "break;" from the
            // while() loop to immediately process the MPU data
            // .
            // .
            // .
        }

        // reset interrupt flag and get INT_STATUS byte
        mpuInterrupt = false;
        mpuIntStatus = mpu.getIntStatus();

        // get current FIFO count
        fifoCount = mpu.getFIFOCount();
        // check for overflow (this should never happen unless our code is too inefficient)
        if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
            // reset so we can continue cleanly
            mpu.resetFIFO();
            // otherwise, check for DMP data ready interrupt (this should happen frequently)
        } else if (mpuIntStatus & 0x02) {
            // wait for correct available data length, should be a VERY short wait
            while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
            // read a packet from FIFO
            mpu.getFIFOBytes(fifoBuffer, packetSize);

            // track FIFO count here in case there is > 1 packet available
            // (this lets us immediately read more without waiting for an interrupt)
            fifoCount -= packetSize;

    #ifdef OUTPUT_READABLE_QUATERNION
            // display quaternion values in easy matrix form: w x y z
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            // Serial.print("quat\t");
            // Serial.print(q.w);
            // Serial.print("\t");
            // Serial.print(q.x);
            // Serial.print("\t");
            // Serial.print(q.y);
            // Serial.print("\t");
            // Serial.println(q.z);
    #endif

    #ifdef OUTPUT_READABLE_EULER
            // display Euler angles in degrees
    //         mpu.dmpGetQuaternion(&q, fifoBuffer);
    //         mpu.dmpGetEuler(euler, &q);
    //         Serial.print("euler\t");
    //         Serial.print(euler[0] * 180/M_PI);
    //         Serial.print("\t");
    //         Serial.print(euler[1] * 180/M_PI);
    //         Serial.print("\t");
    //         Serial.println(euler[2] * 180/M_PI);
    #endif

    #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            *roll = ypr[0] * 180/M_PI;
            *pitch = ypr[1] * 180/M_PI;
            *yaw = ypr[2] * 180/M_PI;
            Serial2.print("ypr\t");
            Serial2.print(ypr[0] * 180/M_PI);
            Serial2.print("\t");
            Serial2.print(ypr[1] * 180/M_PI);
            Serial2.print("\t");
            Serial2.println(ypr[2] * 180/M_PI);
    #endif

    #ifdef OUTPUT_READABLE_REALACCEL
            // display real acceleration, adjusted to remove gravity
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            // Serial.print("areal\t");
            // Serial.print(aaReal.x);
            // Serial.print("\t");
            // Serial.print(aaReal.y);
            // Serial.print("\t");
            // Serial.println(aaReal.z);
    #endif

    #ifdef OUTPUT_READABLE_WORLDACCEL
            // display initial world-frame acceleration, adjusted to remove gravity
            // and rotated based on known orientation from quaternion
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
            // Serial.print("aworld\t");
            // Serial.print(aaWorld.x);
            // Serial.print("\t");
            // Serial.print(aaWorld.y);
            // Serial.print("\t");
            // Serial.println(aaWorld.z);
    #endif

    #ifdef OUTPUT_TEAPOT
            // display quaternion values in InvenSense Teapot demo format:
            teapotPacket[2] = fifoBuffer[0];
            teapotPacket[3] = fifoBuffer[1];
            teapotPacket[4] = fifoBuffer[4];
            teapotPacket[5] = fifoBuffer[5];
            teapotPacket[6] = fifoBuffer[8];
            teapotPacket[7] = fifoBuffer[9];
            teapotPacket[8] = fifoBuffer[12];
            teapotPacket[9] = fifoBuffer[13];
            Serial.write(teapotPacket, 14);
            teapotPacket[11]++; // packetCount, loops at 0xFF on purpose
    #endif

            // blink LED to indicate activity
            // blinkState = !blinkState;
            // digitalWrite(LED_PIN, blinkState);
        }

    #endif
    }
The solver I'm using is fixed-step discrete solver.

I build the S-function and then the model successfully. When I run the simulation in the external mode using Arduino mega there are **jump and glitches** in the output raw, pitch and roll angles as shown in the [![figures][1]][1]
However, when I plotted the [same code](https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino) through Arduino IDE and monitor data on serial plotter there is no glitches and jumps in angles.
I have also change the baud rate to 115200, solver to auto and sample time of s-function but the problem remain to persist.
Any help would be appreciated!
Thanks in advance!

  [1]: https://i.stack.imgur.com/qhAAy.png

body: Measurement sometime lost due to serial communications between Arduino and Simulink. So raw data have some glitches in output values. In order to solve the issue, we have to use state estimation to solve this problem.


body:
To add to the answer above, you are limited by the serial speed of the USB, i.e. USB 2.0 is around 12 Mbps, as well as what your hardware can manage. Also, Simulink uses about 25% of each time step simply for maintaining communication and it is unclear how bandwidth is used by this.
A simple rule of thumb is to work out how much data you are trying to log and at what frequency as this should give you an idea if you are trying to log too much and hence Simulink won't catch all the data and you end up with the blip you have in the scope.
For context, I have been making a wheel speed calculation algorithm and was losing data simply because it wasn't possible to log the volume of data I wanted at high frequency (i.e. 5000 Hz). If you think about logging 3 int8 values at 5000 Hz you are talking 120 kkps, this should give some idea as to how this can get out of control with more signals or larger data types like double.


message:
Attiny85 route vcc though output pin

I'm still learning the basics so please bare with me if something seems unclear ;-)

I want to hook up an Attiny85 to a WiFi module (esp8266) and 2 sensors. The VCC will be provided by a battery pack and a step-up/step-down converter to ensure steady voltage without too much efficiency loss. Right now the modules are all hooked up to the VCC rail, together with the Attiny85 in one circuit.

I would like to take a sample, and then make as much of the circuit power down until the next reading with a 2 minute interval or so.

While looking for power saving modes for the esp8266 and struggling a bit with it, it got me thinking. What if I let Attiny85 handle the WiFi and sensors circuit via an OUTPUT pin and just turn that high or low. I read somewhere that an OUTPUT pin would not be able to supply as much current as if it was directly connected. That would probably be the case for me here since the WiFi module draws significant current.

Maybe using a transistor to "flip the switch" be a good solution instead if that is the case?

So my question is, is my way of thinking here even viable? How do I know what kind of max current can go through an OUTPUT pin?

body:
What you want is a P-channel MOSFET to control the power. Something with a nice low "logic level" gate threshold.

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/oTAPq.png)

<!-- End schematic -->

R1 keeps it switched off.  Set the output to LOW to pull the gate down and enable the MOSFET.

Be sure to "stop" your Serial connection and set both TX and RX pins to INPUT to prevent damage to the ESP8266 (or ATTiny) while powered off.


message:
Is an atmega 2560 board compatible with the Adafruit Trellis?

I want to build a custom midi controller for my computer, and yes, Adafruit has a mini Untz project. For my purposes, I need more analog inputs than the Leonardo, and the only other option I can find is the atmega 2560. Can i use that?

body:
MIDI comes in many different arrangements.

The two most important ones for you are "MIDI Over USB" and "Traditional Serial MIDI".

The former encapsulates MIDI messages and sends them over USB to the computer. This is what you normally get when you plug in a USB-based MIDI instrument, or a USB to MIDI adapter cable.

The latter is a simple serial port running at a specific baud rate. It's generally opto-isolated as well.

On the Leonardo you can do either of those methods (you haven't mentioned which you use), but on the ATMega2560 you can only do the latter (that is, connect the board to a USB to MIDI adaptor cable).  However the Arduino Mega2560 (Note: this is a board, what *you* talk about is *a bare chip*) has a USB interface chip that [can be re-programmed to look like MIDI](https://www.arduino.cc/en/Hacking/MidiWith8U2Firmware).  That will bridge between the "traditional serial MIDI" to the "MIDI over USB". However doing so may impare your ability to program the board.

Another option is to use some [PC-based Serial-To-MIDI bridge software](http://projectgus.github.io/hairless-midiserial/) which reads normal Serial data as provided by the Arduino and converts it into MIDI signals within your computer.

A third option is to step away from Arduino and choose a board that has both a native USB interface (with MIDI support in software) and more analog inputs.  A board such as one of the Teensy 3.x range would probably suit you well.


message:
Factory Pattern on Arduino

I'm looking to create a [factory pattern][1] to identify which of N objects is attached to my `Serial` port. Assuming each object has a unique response to the input stream `"What topic is this?"`, How can I get my `ScienceFactory` class to create my `Science` subclasses?

**EDIT 2** To clarify,

 - *Arduino* sends `identification query` to *device*.
 - *Device* responds with`identification string`
 - *Arduino* receives `identification string`
 - *Arduino* constructs correct `Science Child`

Looking at various examples, I've been able to get the following skeleton code:

    class ScienceFactoy
    {
        public:
          enum Subject {Biology, Chemistry, Physics};
          enum Subject Topic;
          bool GetTopic();
    };

    bool ScienceFactoy::GetTopic()
    {
        Serial.println("What Topic is this?");
        /*The Device will respond with "Biology", "Chemestry" or "Physics"
        over Serial*/

        Topic=Biology;
          /*Instead of writing the Serial.read() logic,
          let's pretend the device is a Biology device*/

        if(Topic==Biology)
        {
            //Create Biology Science Class
            return true;
        }
        if(Topic==Chemistry)
        {
            //Create Chemistry Science Class
            return true;
        }
        if(Topic==Physics)
        {
            //Create Physics Science Class
            return true;
        }
        else
        {
            return false;
        }
    }

    class Science
    {
        public:
          enum Subject {Biology, Chemistry, Physics};
          enum Subject Topic;
          //bool takeAttendance()
          //virtual void TestStudents();
          //virtual void PopQuiz();
          virtual void Free() = 0;
    };

    class Biology : public Science
    {
        public:
        Biology(){Serial.println("Ready For Bio");}
          //bool DissectFrogs(){}
    };

    class Chemistry : public Science
    {
        public:
        Chemistry(){Serial.println("Ready For Chem");}
          //bool MixChemicals(){}
    };

    class Physics : public Science
    {
        public:
        Physics(){Serial.println("Ready For Physics");}
          //bool OpticsLab(){}
    };

    Science ConnectedClass;

    void setup() {
      Serial.begin(9600);
      ScienceFactory ClassAtSerialPort; /*(Something happens that redefines
      ClassAtSerialPort to be the correct class)*/
      /*SerialOut "Ready For Bio\n" should happen here*/
      ConnectedClass=ClassAtSerialPort;

    }

    void loop() {
      if(ConnectedClass.Topic==Biology){DissectFrogs();};

    }

However, I don't know where to go from here as my code is Arduino specific. (**Edit** changed the code so to something that compiles)

  [1]: https://www.c-sharpcorner.com/UploadFile/napanchal/factory-pattern-in-VB-Net/

body:
This is not a simple solution because of the way your Factory and Science classes are structured.

Your Science class needs to hold an actual instance of itself for use when the loop wants to call the children.  This instance will be called 'device' in my example.

    class Science
    {
        public:
          enum Subject {Biology, Chemistry, Physics};
          enum Subject Topic;
          //bool takeAttendance()
          //virtual void TestStudents();
          //virtual void PopQuiz();
          virtual void Free() = 0;
          Science* device;
    };

In your GetTopic() call you then need to instantiate the actual child class

    if(Topic==Biology)
    {
        //Create Biology Science Class
        device = new Biology(); // with appropriate parms
        return true;
    }

Then in your setup() you have to use the class that was created

    ConnectedClass=ClassAtSerialPort.device;

So in the loop() code you call call the device specific method.

    void loop() {
      if(ConnectedClass.Topic==Biology){connectedClass.doScience();};

    }

There is problem with your approach you might still need to resolve.  Relying on polymorphism like this is typically done by creating a common method in the parent that all the children override (ex. `doScience()`) and each child class does whatever is appropriate.  You can have class specific methods but then you'll likely need to cast the device to the specifc class first.


message:
RGB led strip is too dim

I'm following [this tutorial][makezinetutorial] to build an Arduino powered RGB led strip controller but I'm facing two problems:

1. When I use `digitalOutput` the lights are too dim.
2. When I use `PWM` the leds change so slightly that I can barely detect a change.

These are the parts I'm using:

- Wemos D1 mini
- a USB cable to power the Wemos
- 1k ohm resistors
- TIP31c transistors
- A power outlet 12V 1A to power the strip (which works fine with the original controller unit)

The circuit connected as presented in the tutorial (like the circuit below) doesn't work, the board does not start.

If I disconnect the board GND from the outlet GND then the board starts but the leds are too dim to be visible

What am I doing wrong?

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/OJsdj.png)

<!-- End schematic -->

  [makezinetutorial]: https://makezine.com/projects/android-arduino-led-strip-lights/

body:
The Wemos D1 Mini is a 3.3V device. With a 1k base resistor, the most base current you're going to get is (3.3V / 1k ohm) = 3.3mA.

Looking at the [datasheet][1], the current gain (h_FE) for the TIP31 transistor is no more than 50. So the maximum current you will pass from collector to emitter is 50*3.3mA = 165mA.

Your base resistor is too large and is limiting the current to your LED strip to no more than 165mA per channel. Try reducing the base resistor to 150 ohm. The TIP31 can handle continuous collector current of 3A, so you ought to be safe with a 1A power supply, and 150 ohm resistor.

**UPDATE:**

Per @Gerben's comment, the ESP8266 can source a maximum of 12mA from a GPIO pin, so you should not use lower than a 225 ohm base resistor on the initial TIP31. A Darlington pair would look something like:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/poqBo.png)

<!-- End schematic -->

  [1]: https://www.mouser.com/ds/2/68/tip31-845511.pdf


message:
I have the error: expected unqualified-id before 'if'

This is my Sketch or code:

    const int EchoPin = 5;
    const int TriggerPin = 6;
    const int LedPin = 13;

    void setup() {
     Serial.begin(9600);
     pinMode(LedPin, OUTPUT);
     pinMode(TriggerPin, OUTPUT);
     pinMode(EchoPin, INPUT);
     pinMode(13, OUTPUT);
    }

    void loop() {
     int cm = ping(TriggerPin, EchoPin);
     Serial.print("Distancia: ");
     Serial.println(cm);
     delay(1000);
    }

    int ping(int TriggerPin, int EchoPin) {
     long duration, distanceCm;
     digitalWrite(TriggerPin, LOW);
     delayMicroseconds(4);
     digitalWrite(TriggerPin, HIGH);
     delayMicroseconds(10);
     digitalWrite(TriggerPin, LOW);
     duration = pulseIn(EchoPin, HIGH);
     distanceCm = duration * 10 / 292/ 2;
     return distanceCm;
    }

    if (distanceCm <= 20) {
     digitalWrite(13, HIGH);
    }

    if (distanceCm >= 20) {
     digitalWrite(13, LOW);
    }

The error appears in the second if.

body:
The error is occurring because you have 2 **if** statements outside of a function. You could move them into the **ping()** function which would fix the error but there seems to be a logic error with the 2 if statements as well.

If **distanceCm** is 20, both if statements execute one right after another, so I doubt you'll see the LED turn on. Perhaps an **if/else** might work.

    if(distanceCm < 21){
      digitalWrite(13, HIGH);
    }
    else{
      digitalWrite(13, LOW);
    }


body:
Error is because you close your ping method  before the "if (distanceCm >= 20)" clausule. This is a correct code:

    const int EchoPin = 5;
    const int TriggerPin = 6;
    const int LedPin = 13;

    void setup() {
     Serial.begin(9600);
     pinMode(LedPin, OUTPUT);
     pinMode(TriggerPin, OUTPUT);
     pinMode(EchoPin, INPUT);
     pinMode(13, OUTPUT);
    }

    void loop() {
     int cm = ping(TriggerPin, EchoPin);
     Serial.print("Distancia: ");
     Serial.println(cm);
     delay(1000);
    }

    int ping(int TriggerPin, int EchoPin) {
     long duration, distanceCm;
     digitalWrite(TriggerPin, LOW);
     delayMicroseconds(4);
     digitalWrite(TriggerPin, HIGH);
     delayMicroseconds(10);
     digitalWrite(TriggerPin, LOW);
     duration = pulseIn(EchoPin, HIGH);
     distanceCm = duration * 10 / 292/ 2;
      if (distanceCm <= 20) {
     digitalWrite(13, HIGH);
    }

    if (distanceCm >= 20) {
     digitalWrite(13, LOW);
    }
     return distanceCm;
    }


message:
Writing "theremin" outputs to a MIDI file on an SD card

I am making a musical instrument (theremin simulator). I want there to be a "record" capability which stores the volume and note the user is playing, into a MIDI file. Note this doesn't actually record audio, just data for the frequency and volume at a certain point in time.

So far I've done some research and have found how to play MIDI files (which is useful and I plan to take this on as well) and read/write to SD cards. However I haven't found a source which allows me to create and produce MIDI files.

How should I accomplish this feature?

Specs:

 - I am using an Arduino Nano, I have an Uno too if needed
 - The SD card is a 64GB micro SD, inserted into an SD adapter, with header pins soldered onto it. (I am too cheap to buy an actual shield)
 - It was previously XCSD, I formatted it to FAT32 to be compatible with Arduino

Also: I am recording from a self built replica of a theremin, which is basically two ultrasonic sensor readings for volume and pitch. Is this "too basic" for a MIDI file type? *(Edit: I guess this is too advanced)*

**EDIT:** This project has been abandoned because of no good way to play **between** semitones (i.e. at specific frequencies), which is what I need for my theremin. Although there is the pitch bend functionality, the amount of pitch bend translates to different frequency changes based on the receiver.

Instead, I will create my own custom file to achieve the record/playback, because using the pitch bend + note method using MIDI is just too much work and it won't be compatible with other devices anyway.

Nick Gammon's answer is really thorough for those who **only** need to record/play specific **tones and semitones** in MIDI format.

Thanks

body:
The short answer would be "yes, it is possible". There are lots of gadgets around that record MIDI. They would have microprocessors in them, and they would have something like an SD card, which itself is like EEPROM in concept.

You may possibly have problems with storing the notes in RAM, and then writing them to the SD card fast enough not to lose some. Knowing the rate at which notes would arrive, the speed of the SD card, and the type of Arduino would help to answer if your specific case was likely to work.

I wrote a [sketch that reads MIDI](http://www.gammon.com.au/forum/?id=12746) which shows that it is certainly possible to receive MIDI data and display it. Video of it running is [here](https://vimeo.com/80328016).

<s>I don't personally know the format of MIDI files, but it is [well documented](https://www.midi.org/specifications-old/item/standard-midi-files-smf).</s>

(Edit) I do now - see further down.

Writing to SD cards is well documented. Making your idea work would be a case of taking stuff (like my code to decode MIDI), code to write to SD cards, and knowing the correct format.

---

**(Edited to add)**

See [Standard MIDI-File Format Spec. 1.1](http://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html) for an example of producing MIDI data. Also see [The MIDI File Format](https://www.fileformat.info/format/midi/corion.htm) and the [Standard MIDI File (SMF) Format](http://midi.teragonaudio.com/tech/midifile.htm)

Your basic technique would need to be (as suggested by gabonator):

* Write a header chunk to the file, for example:

        4D 54 68 64   // MThd
        00 00 00 06   // chunk length
        00 00         // format 0
        00 01         // one track
        00 60         // 96 pulses per quarter-note

* Write a track chunk to the file (the length will be updated later)

        4D 54 72 6B   // MTrk
        00 00 00 00   // <-- length to be updated later

* Write instrument configurations (with time delta values of zero), as an example from that page:

        00  FF 58 04  04 02 18 08  // 4 bytes; 4/4 time; 24 MIDI clocks/click,
                                   // 8 32nd notes/ 24 MIDI clocks
                                   // (24 MIDI clocks = 1 crotchet = 1 beat)
        00  FF 51 03  07 A1 20     // 3 bytes: 500,000 µsec/ quarter note
                                   // = 120 beats/minute (500000 in hex is 0x07A120)
        00  C0 05                  // Ch.1 Program Change 5 = GM
                                   // Patch 6 = Electric Piano 2

* When the player plays something, subtract the time that s/he last did something from the time now. This will give you the delta time.

* Convert the time difference to ticks. From the header line above we have 96 pulses per quarter note (PPQ), and 500,000 µs (500 ms) per quarter note. Thus one second would be two quarter notes (2 beats per second, and therefore 120 beats per minute) and one second is therefore 192 ticks). Therefore the number of ticks, based on the time difference in milliseconds, would be:

        unsigned long ticks = (time_difference * 192) / 1000

* Output the delta time as a variable length number, where the high order bit is set for each byte, as necessary, until what is left is <= 0x7F. The page above gives sample code for that. For example, for a delta time of 199 ticks:

        Decimal time of 199 ticks -> 0xC7
        0xC7 -> 0b11000111
        Since that exceeds 127, split into two bytes:

        10000001  (the high order bits)
         ^^^^^^^  <- high order bits (the MSB must be one)
        01000111  (the low-order 7 bits)
         ^^^^^^^  <- low order bits (the MSB must be zero)

        Result is 0x81 0x47

    Longer times may require even more bytes.

    Something like this should do it (adapted from the linked page). Just change the Serial.write line to output to your disk file.

        void WriteVarLen (unsigned long value)
          {
          unsigned long buffer;

          buffer = value & 0x7f;
          while ((value >>= 7) > 0)
            {
            buffer <<= 8;
            buffer |= 0x80;
            buffer |= value & 0x7f;
            }

          while (true)
            {
            Serial.write (buffer & 0xFF);
            if (buffer & 0x80)
              buffer >>= 8;
            else
              break;
            }
          }   // end of WriteVarLen

* Follow the delta time immediately by the "note on" or "note off" byte (depending on whether they started or stopped playing a note). For example, "note on" for channel 1 would be 0x90 because 0x9n is a note on command and n is the channel number, zero relative. A "note off" for channel 1 would be 0x80.

* Follow the "note on" or "note off" by the note number (in other words, *which* note was just played or released) - one byte.

        Octave #  Note Numbers in decimal
                  C   C#  D   D#  E   F   F#  G   G#  A   A#  B
        -1         0   1   2   3   4   5   6   7   8   9  10  11
        0         12  13  14  15  16  17  18  19  20  21  22  23
        1         24  25  26  27  28  29  30  31  32  33  34  35
        2         36  37  38  39  40  41  42  43  44  45  46  47
        3         48  49  50  51  52  53  54  55  56  57  58  59
        4         60  61  62  63  64  65  66  67  68  69  70  71
        5         72  73  74  75  76  77  78  79  80  81  82  83
        6         84  85  86  87  88  89  90  91  92  93  94  95
        7         96  97  98  99 100 101 102 103 104 105 106 107
        8        108 109 110 111 112 113 114 115 116 117 118 119
        9        120 121 122 123 124 125 126 127

    Typically middle C is considered to be C4 (C in the 4th octave), however apparently that can vary between devices.

*  Then output the velocity (one byte). A velocity of (decimal) 32 would be soft, 64 would be medium, 96 would be loud. The range for velocities is 0 to 127.

* Repeat the above (except for writing the chunks and the configuration) until the player decides to stop playing.

* Write an "end of track" marker:

        00  FF 2F 00  // Delta time zero, end of track
* Then seek back to the start of the file + where the length bytes are (18 bytes into the file by the looks of it) and update the length bytes (4 bytes).

---

# Example of producing a MIDI file

This example code writes out a MIDI file. As an input device I used a 16-key keypad like this:

[![Keypad matrix][1]][1]

The columns were connected to pins 0, 1, 2, 3 of the Arduino Uno, and the rows to pins 4, 5, 6, 7. This makes the ribbon cable from the keypad keep the pins in a natural order. If you use different pins just change the `keys` array in the sketch.

The library for keypads that I used is available at <https://github.com/nickgammon/Keypad_Matrix>

This particular library supports n-key rollover and key-down and key-up events. That is particularly useful for music, because it lets you hold multiple keys down at once, and the appropriate events will be generated. Obviously you need a key-down event to generate "note on" and a key-up event to generate "note-off".

I laid out the keys like this:

    C     C#    D     D#
    E     F     F#    G
    G#    A     A#    B
    Down  Soft  Up    Record

* There is a "recording" LED connected to A0 which lights up when you start recording (by pressing the Record button).

* Press the Record button again to stop recording and finalize the file. It is important to stop recording properly and not just power off the device, because the length of the file needs to be written near the start.

* Press (and hold) Down alongside with another note to play an octave lower. Press (and hold) Up alongside with another note to play an octave higher.

* Press (and hold) Soft alongside with another note to play at a softer velocity.

Using a keypad matrix is logical, because most keyboard devices would use a matrix, to reduce the number of wires you have to run.

Note that the matrix needs diodes wired for each switch as described [here](http://www.gammon.com.au/forum/?id=14175) because otherwise if you press 3 or more keys at once you will get "ghost" keys.

In my case I opened up the commercial keypad and soldered in the diodes.

---

I also used a Micro-SD breakout adapter, connected to the SPI pins of the Arduino, like this:

[![Micro SD adapter][2]][2]

---

The SDFat library was an archived one that I keep here: <http://gammon.com.au/Arduino/SdFat-master.zip> (2.2 Mb)

Unzip that file, and from within the folders inside it, copy the SdFat folder into your "libraries" folder (which is under your Arduino sketchbook folder - not inside the Arduino application folder). Then restart the Arduino IDE.

The code definitely compiles with that (with a handful of warnings). The later library from <https://github.com/greiman/SdFat> may be an improvement but I haven't tested that.

---

To keep track of file numbers I used the EEPROMAnything library, a copy of which can be found at <http://gammon.com.au/Arduino/EEPROMAnything.zip>

Each time you start a new recording it adds one to the file number, which wraps around to 0000 once it reaches 9999.

---

If there is an error initializing the file system (eg. no SD card) then the LED blinks slowly. If the file can't be created the LED blinks rapidly.

---

You can choose a MIDI instrument by changing the line:

    const byte PATCH_NUMBER = 4;   // electric piano 1

---

# Code

<!-- language: lang-c++ -->

    /*
     Sketch to write to a MIDI file from an instrument.
     Author: Nick Gammon
     Date:   10th May 2018

     Copyright 2018 Nick Gammon.

     PERMISSION TO DISTRIBUTE

     Permission is hereby granted, free of charge, to any person obtaining a copy of this software
     and associated documentation files (the "Software"), to deal in the Software without restriction,
     including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
     and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
     subject to the following conditions:

     The above copyright notice and this permission notice shall be included in
     all copies or substantial portions of the Software.

     LIMITATION OF LIABILITY

     The software is provided "as is", without warranty of any kind, express or implied,
     including but not limited to the warranties of merchantability, fitness for a particular
     purpose and noninfringement. In no event shall the authors or copyright holders be liable
     for any claim, damages or other liability, whether in an action of contract,
     tort or otherwise, arising from, out of or in connection with the software
     or the use or other dealings in the software.

    */

    #include <Keypad_Matrix.h>
    #include <SdFat.h>
    #include <EEPROM.h>
    #include <EEPROMAnything.h>

    // For MIDI numbers see: http://www.pjb.com.au/muscript/gm.html
    const byte PATCH_NUMBER = 4;   // electric piano 1

    const byte RECORDING_LED = A0;

    // bottom row changes things
    const char DOWN_OCTAVE  = '-';
    const char SOFT         = 's';
    const char UP_OCTAVE    = '+';
    const char RECORD       = 'r';

    // how the keypad has its keys laid out
    // capital letters are for sharps
    const byte ROWS = 4;
    const byte COLS = 4;
    const char keys[ROWS][COLS] = {
      {'c', 'C', 'd', 'D'},
      {'e', 'f', 'F', 'g'},
      {'G', 'a', 'A', 'b'},
      {DOWN_OCTAVE, SOFT, UP_OCTAVE, RECORD},  // - = down octave, s = soft, + = up octave, r = start/stop record
    };

    const byte colPins[COLS] = {0, 1, 2, 3}; //connect to the column pinouts of the keypad
    const byte rowPins[ROWS] = {4, 5, 6, 7}; //connect to the row pinouts of the keypad

    // Create the Keypad
    Keypad_Matrix kpd = Keypad_Matrix( makeKeymap (keys), rowPins, colPins, ROWS, COLS );

    // file system object
    SdFat sd;
    const byte chipSelect = SS;

    // the current file we are recording to
    SdFile myFile;
    // are we recording right now?
    bool recording = false;

    const byte MIDI_META_EVENT = 0xFF;
    const byte MIDI_SET_TEMPO  = 0x51;
    const byte MIDI_TIME_SIGNATURE = 0x58;
    const byte MIDI_END_OF_TRACK = 0x2F;
    const byte MIDI_PROGRAM_CHANGE = 0xC0;
    const byte MIDI_NOTE_ON = 0x90;   // channel 1
    const byte MIDI_NOTE_OFF = 0x80;  // channel 1

    struct
      {
      char magic [4]; // MThd
      uint32_t length;
      uint16_t format;
      uint16_t tracks;
      uint16_t PPQ;    // pulses per quarter note
      } chunkHeader;

    struct
      {
      char magic [4]; // MTrk
      uint32_t length;
      } trackHeader;

    unsigned long trackHeaderPosition;
    unsigned long timeLastAction;
    int           nextFileNumber;

    uint32_t changeEndianness32(uint32_t val)
    {
      return (val << 24) |
            ((val <<  8) & 0x00ff0000) |
            ((val >>  8) & 0x0000ff00) |
            ((val >> 24) & 0x000000ff);
    } // end of changeEndianness32

    uint16_t changeEndianness16(uint16_t val)
    {
      return (val << 8) | ((val >> 8) & 0x00ff);
    } // end of changeEndianness16

    void showError (const int delayTime)
      {
      while (true)
        {
        digitalWrite (RECORDING_LED, HIGH);
        delay (delayTime);
        digitalWrite (RECORDING_LED, LOW);
        delay (delayTime);
        }

      } // end of showError

    void startRecording ()
      {
      EEPROM_readAnything (0, nextFileNumber);
      if (nextFileNumber > 9999 || nextFileNumber < 0)
        nextFileNumber = 0;

      char name[15];
      sprintf (name, "SONGd.MID", nextFileNumber++);

      // open the file for writing
      if (!myFile.open(name, O_WRITE | O_CREAT | O_TRUNC))
        showError (100);  // fast flash - never returns

      // update EEPROM for next time
      EEPROM_writeAnything (0, nextFileNumber);

      recording = true;
      digitalWrite (RECORDING_LED, HIGH);
      memcpy (chunkHeader.magic, "MThd", sizeof (chunkHeader.magic));
      chunkHeader.length = changeEndianness32 (
                           sizeof (chunkHeader.format) +
                           sizeof (chunkHeader.tracks) +
                           sizeof (chunkHeader.PPQ));

      chunkHeader.format = changeEndianness16 (0);
      chunkHeader.tracks = changeEndianness16 (1);
      chunkHeader.PPQ = changeEndianness16 (96);
      myFile.write (&chunkHeader, sizeof (chunkHeader));
      memcpy (trackHeader.magic, "MTrk", sizeof (trackHeader.magic));
      trackHeader.length = 0;   // to be filled in later
      trackHeaderPosition = myFile.curPosition ();
      myFile.write (&trackHeader, sizeof (trackHeader));

      struct
        {
        byte deltaTime = 0;
        byte metaCode [2] = { MIDI_META_EVENT, MIDI_TIME_SIGNATURE };
        byte length = 4;
        byte sig [2] = { 4, 2 };  // 4/4 time (denominator of 2 is 2^2)
        byte clocksPerClick = 24;  // MIDI clocks/click
        byte clocksPerBeat  = 8;
        }  timeSignature;

     struct
        {
        byte deltaTime = 0;
        byte metaCode [2] = { MIDI_META_EVENT, MIDI_SET_TEMPO };
        byte length = 3;
        byte usPerQuarterNote [3] = { 0x07, 0xA1, 0x20 };  // that is: 500000 µs per beat
        }  tempo;

     struct
        {
        byte deltaTime = 0;
        byte message =   MIDI_PROGRAM_CHANGE;
        byte patchNumber = PATCH_NUMBER;
        }  programChange;

      myFile.write (&timeSignature, sizeof timeSignature);
      myFile.write (&tempo, sizeof tempo);
      myFile.write (&programChange, sizeof programChange);
      timeLastAction = millis ();
      } // end of startRecording

    void stopRecording ()
      {
      struct
        {
        byte deltaTime = 0;
        byte metaCode [2] = { MIDI_META_EVENT, MIDI_END_OF_TRACK };
        byte length = 0;
        }  endOfTrack;

      // write out "end of track" message
      myFile.write (&endOfTrack, sizeof endOfTrack);
      // find where we are
      unsigned long finalPosition = myFile.curPosition ();
      // go back to where the track header is
      myFile.seekSet (trackHeaderPosition);
      // work out how long the data was (excluding the headers)
      trackHeader.length = changeEndianness32 (finalPosition - trackHeaderPosition - sizeof (trackHeader));
      // update the file length
      myFile.write (&trackHeader, sizeof (trackHeader));

      myFile.close ();
      // ensure flushed to disk
      myFile.SdBaseFile::sync();

      // no longer recording, turn off recording LED
      recording = false;
      digitalWrite (RECORDING_LED, LOW);
      } // end of stopRecording

    void writeVarLen(unsigned long value)
    {
      unsigned long buffer;

      buffer = value & 0x7f;
      while ((value >>= 7) > 0)
      {
        buffer <<= 8;
        buffer |= 0x80;
        buffer |= value & 0x7f;
      } // end of while

      while (true)
      {
        myFile.write ((byte) (buffer & 0xFF));
        if (buffer & 0x80)
          buffer >>= 8;
        else
          break;
      } // end of while

    }   // end of writeVarLen

    // turn the keypad code into a note number
    byte codeToNote (const char which)
    {
      char notes [] = "cCdDefFgGaAb";
      char * pos = strchr (notes, which);
      if (pos == NULL)
        return 0;
      return pos - notes + 60;  // start at middle C (C4)
    } // end of codeToNote

    // do a note on or note off
    void doNoteAction (const char which, const byte action)
    {
      // we need to work out how many milliseconds have elapsed
      unsigned long now = millis ();
      unsigned long deltaTime = now - timeLastAction;
      // remember when we did this
      timeLastAction = now;
      // write out the delta time
      writeVarLen ((deltaTime * 192) / 1000);

      // note information
      struct
        {
        byte noteOn;
        byte whichNote;
        byte velocity;
        } playNote;

      playNote.noteOn = action;
      playNote.whichNote = codeToNote (which);
      if (kpd.isKeyDown (DOWN_OCTAVE))
        playNote.whichNote -= 12;  // one octave down
      else if (kpd.isKeyDown (UP_OCTAVE))
        playNote.whichNote += 12;  // one octave up

      playNote.velocity = 64;      // medium velocity
      if (kpd.isKeyDown (SOFT))
        playNote.velocity = 32;    // softer

      myFile.write (&playNote, sizeof (playNote));
    } // end of doNoteAction

    void startPlaying (const char which)
      {
      doNoteAction (which, MIDI_NOTE_ON);
      } // end of startPlaying

    void stopPlaying (const char which)
      {
      doNoteAction (which, MIDI_NOTE_OFF);
      } // end of stopPlaying

    void keyDown (const char which)
      {
      switch (which)
        {
        case 'c':
        case 'C':
        case 'd':
        case 'D':
        case 'e':
        case 'f':
        case 'F':
        case 'g':
        case 'G':
        case 'a':
        case 'A':
        case 'b':
          startPlaying (which);
          break;

        default:
          break;
        } // end of switch on which key
      } // end of keyDown

    void keyUp (const char which)
      {
      switch (which)
        {
        case RECORD:
          if (recording)
            stopRecording ();
          else
            startRecording ();
          break;

        case 'c':
        case 'C':
        case 'd':
        case 'D':
        case 'e':
        case 'f':
        case 'F':
        case 'g':
        case 'G':
        case 'a':
        case 'A':
        case 'b':
          stopPlaying (which);
          break;

        default:
          break;
        } // end of switch on which key
      } // end of keyUp

    void setup()
    {
      kpd.begin ();
      kpd.setKeyDownHandler (keyDown);
      kpd.setKeyUpHandler   (keyUp);
      pinMode (RECORDING_LED, OUTPUT);

      if (!sd.begin (chipSelect, SPI_HALF_SPEED))
         showError (500);  // never returns

    } // end of setup

    void loop()
    {
      kpd.scan ();
    } // end of loop

---

> I am recording from a self built replica of a theremin, which is basically two ultrasonic sensor readings for volume and pitch. Is this "too basic" for a MIDI file type?

It looks like this could be possible by using the MIDI "pitch bend" message. You would need to determine where your note value was (presumably most of the time *between* the natural notes like C and C#) and then send a bend message or "Pitch Wheel Change" (0xE0 for channel 1) to modify the main note. The main note would need to be updated if you moved more than a couple of semitones away.

See:

* https://en.wikipedia.org/wiki/Pitch_wheel
* http://sites.uci.edu/camp2014/2014/04/30/managing-midi-pitchbend-messages/

  [1]: https://i.stack.imgur.com/1Z0Nn.jpg
  [2]: https://i.stack.imgur.com/1Jccw.jpg


body: Yes, read the [MIDI file format specification](https://www.csie.ntu.edu.tw/~r92092/ref/midi/). Create a single track midi file and [append](https://arduino.stackexchange.com/questions/37288/adding-data-to-an-sd-card-file) just note press / release commands / pitch or volume changes and delta times (reverse conversion of delta times to milliseconds is [explained here](https://stackoverflow.com/questions/5288593/how-to-convert-midi-timeline-into-the-actual-timeline-that-should-be-played/5297236#5297236)). When you finish recording, just seek to the beginning of the file and update the track length value (total size of the appended buffer of midi commands)