Arduino Due: Difference between revisions

From Nottinghack Wiki
Jump to navigation Jump to search
Line 393: Line 393:
   delay(500);
   delay(500);
    
    
}
</pre></code>
== Audio play ported to SDfat beta ==
<code><pre>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Audio.h>
// SD chip select pin
const uint8_t chipSelect = 10;
// file system
SdFat sd;
// test file
SdFile file;
// Serial output stream
ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))
void setup()
{
  Serial.begin(115200);
  while (!Serial){}  // wait for Leonardo/Due
  cout << pstr("\nHello there!\n  due_audio  test 1  \n");
}
void loop() {
  while (Serial.read() >= 0) {}
  cout << pstr("Type any character to start\n");
  while (Serial.read() <= 0) {}
  delay(400);  // catch Due reset problem
  cout << pstr("Free RAM: ") << FreeRam() << endl;
  // initialize the SD card at SPI_FULL_SPEED for best performance.
  // try SPI_HALF_SPEED if bus errors occur.
  if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt();
  cout << pstr("Type is FAT") << int(sd.vol()->fatType()) << endl;
  // open or create file - truncate existing file.
  if (!file.open("TEST.WAV", O_RDONLY)) {
    error("open failed");
  }
  // 44100Khz stereo => 88200 sample rate
  // 100 mSec of prebuffering.
  Audio.begin(88200, 100);
  int count=0;
  cout << pstr("Playing...") << endl;
  const int S=1024; // Number of samples to read in block
  short buffer[S];
  int c;
  while(1){
    c = file.read(buffer, S);
    if(c==-1) {
      error("read failed");
    }
    // Prepare samples
    int volume = 1024;
    Audio.prepare(buffer, S, volume);
    // Feed samples to audio
    Audio.write(buffer, S);
    // Every 100 block print a '.'
    count++;
    if (count == 100) {
      cout << pstr(".");
      count = 0;
    }
    if(c < S)
      break;
  }
  file.close();
  cout << endl << pstr("End of file. Thank you for listening!") << endl;
}
}
</pre></code>
</pre></code>

Revision as of 21:55, 18 September 2013

Arduino Due
[[{{{image}}}|border|frameless|220px|center]]
Primary Contact Michael Erskine
Created 2013-08-12
Completed {{{completeddate}}}
Dormant {{{dormantdate}}}
Version {{{version}}}
Members {{{members}}}
Manufacturer {{{manufacturer}}}
Model {{{model}}}
Location [[{{{location}}}]]
GitHub / Repo {{{repo}}}
Status prototyping‎
Type Undefined
Live Status {{{livestatus}}}
QR code


The new Arduino Due board is the first Arduino to be based on an ARM Coretex M3 micro (rather than the usual AVR micro). This is still an Atmel chip but it will have more in common with the Mbed, LPCXpresso, etc. At time of writing I am still yet to receive my first Due board but I'm reliably informed that it's in the post!

So what is all the fuss about? Did you even notice any fuss? Well, it's a move away from the old AVR architecture and into a bigger arena. ARM is massive! What we, as Arduino users, get is an Arduino with a shed load more speed, and capacity. There are some potential downsides in the area of legacy Arduino convenience (e.g. the 3.3v logic) but these are small problems for those who appreciate the extra power.

Useful links in these early days:-

This handy comparison table is from one of the sites above - not sure of the origin but I know that the 250k EEPROM for the Due is wrong as it doesn't have any!


Arduino UNO

Arduino Mega

Arduino Due

MCU

ATMega 328

ATMega 2560

AT91SAM3X8E

Architecture

8 bit AVR

8 bit AVR

32 bit ARM Cortex M3

CPU Speed

16Mhz

16Mhz

84 Mhz

Flash Memory

32K

256K

512K

RAM

2K

8K

96K

EEPROM

1K

4K

250K

Digital Pins

14

54

54

PWM Pins

6

15

16

AnalogInputs

6

16

12

DAC

0

0

2

First Due Arrived

OK, Aug 15th 2013, and I've got my first Due clone: a nice red SainSmart Due (http://www.sainsmart.com/sainsmart-due-atmel-sam3x8e-arm-cortex-m3-board.html) for the bargain price of £25 (a UK ebay seller).


Pinout diagram: http://forum.arduino.cc/index.php?topic=132130.0

New Magic

The main new magic is a pair of USB sockets: "programming port" and "native port". We also have an "erase" button which looks scary!

I first set up the Arduino 1.5.2 zip install onto a Windows XP machine and had a jolly old time with the various CDC serial port drivers! After a while everything was pretty nice using the programming port for uploading code and running a small command terminal. I had to employ the while(!Serial); technique to get a reliable startup of my code.

There is a 12-bit DAC onboard and there are exciting new projects that demonstrate impressing WAV audio output. Combined with the 3.3v voltages for cheap SD card interfacing, we have a simple means for adding good quality audio to our projects.

SD card success

I have just enjoyed a success with a direct SPI SD card interface...

Use a freshly formatted SD for best performance.
Type any character to start
Free RAM: 95419
Type is FAT32
File size 5MB
Buffer size 100 bytes
Starting write test.  Please wait up to a minute
Write 109.39 KB/sec
Maximum latency: 345932 usec, Minimum Latency: 8 usec, Avg Latency: 912 usec

Starting read test.  Please wait up to a minute
Read 975.80 KB/sec
Maximum latency: 982 usec, Minimum Latency: 7 usec, Avg Latency: 100 usec

Done

Type any character to start

This uses a beta of the SdFat library as per http://forum.arduino.cc/index.php?topic=135439.0 connecting as shown using the SPI port and a single slave select pin (on digital 10). The SD card happens to be a 4Gb Transcend micro SD in a Kingston adapter. I made the cable from a PC motherboard connector I found at the hackspace.

Here's the "bench" sketch - slight modification!

/*
 * This sketch is a simple binary write/read benchmark.
 */
#include <SdFat.h>
#include <SdFatUtil.h>

// SD chip select pin
const uint8_t chipSelect = 10;

#define FILE_SIZE_MB 5
#define FILE_SIZE (1000000UL*FILE_SIZE_MB)
#define BUF_SIZE 100

uint8_t buf[BUF_SIZE];

// file system
SdFat sd;

// test file
SdFile file;

// Serial output stream
ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  while (!Serial){}  // wait for Leonardo
  cout << pstr("\nUse a freshly formatted SD for best performance.\n");
}
//------------------------------------------------------------------------------
void loop() {
  uint32_t maxLatency;
  uint32_t minLatency;
  uint32_t totalLatency;

  // discard any input
  while (Serial.read() >= 0) {}

  // pstr stores strings in flash to save RAM
  cout << pstr("Type any character to start\n");
  while (Serial.read() <= 0) {}
  delay(400);  // catch Due reset problem
  
  cout << pstr("Free RAM: ") << FreeRam() << endl;

  // initialize the SD card at SPI_FULL_SPEED for best performance.
  // try SPI_HALF_SPEED if bus errors occur.
  if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt();

  cout << pstr("Type is FAT") << int(sd.vol()->fatType()) << endl;

  // open or create file - truncate existing file.
  if (!file.open("BENCH.DAT", O_CREAT | O_TRUNC | O_RDWR)) {
    error("open failed");
  }

  // fill buf with known data
  for (uint16_t i = 0; i < (BUF_SIZE-2); i++) {
    buf[i] = 'A' + (i % 26);
  }
  buf[BUF_SIZE-2] = '\r';
  buf[BUF_SIZE-1] = '\n';

  cout << pstr("File size ") << FILE_SIZE_MB << pstr("MB\n");
  cout << pstr("Buffer size ") << BUF_SIZE << pstr(" bytes\n");
  cout << pstr("Starting write test.  Please wait up to a minute\n");

  // do write test
  uint32_t n = FILE_SIZE/sizeof(buf);
  maxLatency = 0;
  minLatency = 9999999;
  totalLatency = 0;
  uint32_t t = millis();
  for (uint32_t i = 0; i < n; i++) {
    uint32_t m = micros();
    if (file.write(buf, sizeof(buf)) != sizeof(buf)) {
      error("write failed");
    }
    m = micros() - m;
    if (maxLatency < m) maxLatency = m;
    if (minLatency > m) minLatency = m;
    totalLatency += m;
  }
  file.sync();
  t = millis() - t;
  double s = file.fileSize();
  cout << pstr("Write ") << s/t << pstr(" KB/sec\n");
  cout << pstr("Maximum latency: ") << maxLatency;
  cout << pstr(" usec, Minimum Latency: ") << minLatency;
  cout << pstr(" usec, Avg Latency: ") << totalLatency/n << pstr(" usec\n\n");
  cout << pstr("Starting read test.  Please wait up to a minute\n");
  // do read test
  file.rewind();
  maxLatency = 0;
  minLatency = 9999999;
  totalLatency = 0;
  t = millis();
  for (uint32_t i = 0; i < n; i++) {
    buf[BUF_SIZE-1] = 0;
    uint32_t m = micros();
    if (file.read(buf, sizeof(buf)) != sizeof(buf)) {
      error("read failed");
    }
    m = micros() - m;
    if (maxLatency < m) maxLatency = m;
    if (minLatency > m) minLatency = m;
    totalLatency += m;
    if (buf[BUF_SIZE-1] != '\n') {
      error("data check");
    }
  }
  t = millis() - t;
  cout << pstr("Read ") << s/t << pstr(" KB/sec\n");
  cout << pstr("Maximum latency: ") << maxLatency;
  cout << pstr(" usec, Minimum Latency: ") << minLatency;
  cout << pstr(" usec, Avg Latency: ") << totalLatency/n << pstr(" usec\n\n");
  cout << pstr("Done\n\n");
  file.close();
}

Next: port http://arduino.cc/en/Tutorial/SimpleAudioPlayer to use SdFat beta

High Speed Timer - Coretex SysTick

// SysTick example by stimmer
// Slightly modified by msemtd

void setup() {
  Serial.begin(115200);
}

void loop() {
  
  int r=random(200);
  int v=SysTick->VAL;
  int a;
  delayMicroseconds(r);
  v=v-SysTick->VAL;
  if(v<0)v+=84000;
  Serial.print("delayMicroseconds(");
  Serial.print(r);
  Serial.print(") took ");
  Serial.print(v);
  Serial.print(" clock ticks, which when divided by 84 equals ");
  a = v/84;
  Serial.print(a);
  if(a != r){
    Serial.println(" -- FAILED!!!!!!!!!!!!");
  } else {
    Serial.println(" -- ok");
  }
  delay(500);
  
}


Audio play ported to SDfat beta

#include <SdFat.h>
#include <SdFatUtil.h>
#include <Audio.h>
// SD chip select pin
const uint8_t chipSelect = 10;
// file system
SdFat sd;
// test file
SdFile file;
// Serial output stream
ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))

void setup()
{
  Serial.begin(115200);
  while (!Serial){}  // wait for Leonardo/Due
  cout << pstr("\nHello there!\n  due_audio  test 1  \n");
}

void loop() {
  while (Serial.read() >= 0) {}
  cout << pstr("Type any character to start\n");
  while (Serial.read() <= 0) {}
  delay(400);  // catch Due reset problem
  cout << pstr("Free RAM: ") << FreeRam() << endl;
  // initialize the SD card at SPI_FULL_SPEED for best performance.
  // try SPI_HALF_SPEED if bus errors occur.
  if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt();
  cout << pstr("Type is FAT") << int(sd.vol()->fatType()) << endl;
  // open or create file - truncate existing file.
  if (!file.open("TEST.WAV", O_RDONLY)) {
    error("open failed");
  }
  // 44100Khz stereo => 88200 sample rate
  // 100 mSec of prebuffering.
  Audio.begin(88200, 100);
  int count=0;
  cout << pstr("Playing...") << endl;

  const int S=1024; // Number of samples to read in block
  short buffer[S];
  int c;

  while(1){
    c = file.read(buffer, S);
    if(c==-1) {
      error("read failed");
    }

    // Prepare samples
    int volume = 1024;
    Audio.prepare(buffer, S, volume);
    // Feed samples to audio
    Audio.write(buffer, S);

    // Every 100 block print a '.'
    count++;
    if (count == 100) {
      cout << pstr(".");
      count = 0;
    }
    if(c < S)
       break;
  }
  file.close();

  cout << endl << pstr("End of file. Thank you for listening!") << endl;

}