element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Enchanted Objects
  • Challenges & Projects
  • Design Challenges
  • Enchanted Objects
  • More
  • Cancel
Enchanted Objects
Blog 1958 Turntable from the Black Forest - 19: Port my Light Organ from Arduino to SAMA5D4
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Events
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 18 May 2015 5:51 PM Date Created
  • Views 1640 views
  • Likes 1 like
  • Comments 8 comments
  • sama5d4
  • enchanted_player
  • enchanted_objects
  • port
  • arduino
  • xplained_ultra
Related
Recommended

1958 Turntable from the Black Forest - 19: Port my Light Organ from Arduino to SAMA5D4

Jan Cumps
Jan Cumps
18 May 2015

image

 

Now that I have my SAMA5D4 development chain under control, it's time to do something with it.

My first attempt is to move the Genuino sketch made for my light organ to the SAMA5D4.

The design has 4 main steps: sampling, applying a Hamming window function, performing a FFT, drive leds

 

Moving C++ code from one environment to another is straightforward. In essence, the only thing I had to do is switch out the Arduino analogread() and digitalwrite() functions for the SAMA5D4 counterparts.

 

This is such a boring exercise that I'm not going to blog about it.

 

image

 

Partly Success

 

The porting exercise went really smooth. My code passed the build in less than an hour. When I ran it on the board, the results were promising.

The sampling worked, and the LEDS were flashing.

 

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

But the code failed in a part that I didn't expect: the signal processing part.

I did not get a led pattern that was consistent with the Arduino. Even if I applied a single sinus, all 3 leds were flashing.

With a light organ,you expect that the high led is dim when you apply a low frequency input. On my SAMA5D4, the 3 leds were flashing in a pattern, whatever frequency I applied to the input.

 

Debug Time

 

So it's time to debug. The symptoms point to an issue with the signal processing. So I created a testbed on both systems that just do that.

I give the program a fixed array with samples (the same array on both boards).

Then I check the output after the Hamming function and after the FFT.


Here's a subset of the SAMA5D4 output:

samada fixed sample string:
samples :
0,7,14,21,28,35,42,49,56,63,70,77,84,91,98,105,112,119,126,-123,-116,-109,-102,-95,-88,-81,-74,-67,...
window :
0,0,0,0,0,0,0,1,2,3,4,5,7,9,11,13,16,19,23,-25,-26,-26,-27,-27,-27,-27,-26,-25,-24,-22,-20,-18,-16,-13,-9,-6,-2...
fft :
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,


And this is the known good result from the Arduino:

Arduino fixed sample string
samples
0,7,14,21,28,35,42,49,56,63,70,77,84,91,98,105,112,119,126,-123,-116,-109,-102,-95,-88,-81,-74,-67,...
window
0,0,0,0,0,0,0,1,2,3,4,5,7,9,11,13,16,19,23,-25,-26,-26,-27,-27,-27,-27,-26,-25,-24,-22,-20,-18,-16,-13,-9,-6,-2...
fft
9,1,17,226,34,1,26,82,16,9,17,49,2,10,17,5,5,5,13,2,4,13,5,2,2,9,2,1,4,5,1,4,4,1,1,5,1,2,0,5,5,1,2,1,2,1,4,0,4,1,1,5,1,4,1,4,13,2,0,1,5,1,1,1,


It's obvious, isn't it? My port from the FFT lib from Arduino to SAMA5D4 has issues.


image



I'll spend some quality time to see where I made mistakes in the port of that FFT lib. I'll post my findings in a next blog.


For reference, here are the two test beds.


Arduino:

#include <fix_fft.h>


#define MUESTRAS 128           // Numero de muestras para el cálculo de la FFT
#define LOGM 7                 // Logaritmo en base 2 del número de muestras


#define BAJOS_MEDIOS 7         // Nº de banda para el corte entre Bajos y Medios
#define MEDIOS_AGUDOS 35       // Nº de banda para el corte entre Medios y Agudos


#define MAX_PASADAS 10         // Nº de pasadas para el cálculo de los lÃmites


char data[MUESTRAS] = {0,7,14,21,28,35,42,49,56,63,70,77,84,91,98,105,112,119,126,-123,-116,-109,-102,-95,-88,-81,-74,-67,-60,-53,-46,-39,-32,-25,-18,-11,-4,3,10,17,24,31,38,45,52,59,66,73,80,87,94,101,108,115,122,-127,-120,-113,-106,-99,-92,-85,-78,-71,-64,-57,-50,-43,-36,-29,-22,-15,-8,-1,6,13,20,27,34,41,48,55,62,69,76,83,90,97,104,111,118,125,-124,-117,-110,-103,-96,-89,-82,-75,-68,-61,-54,-47,-40,-33,-26,-19,-12,-5,2,9,16,23,30,37,44,51,58,65,72,79,86,93,100,107,114,121};           // Array con los valores muestreados (parte real)
char im[MUESTRAS];             // Array con los valores muestreados (parte imaginaria)


unsigned char salida[MUESTRAS/2];  // Valores obtenidos de la FFT (espectro de 64 bandas)
unsigned char bajos,medios,agudos; // Valores calculados para cada canal


byte  pasada,                            // nº de pasada para el cáculo de los lÃmites
      acumBajos,acumMedios,acumAgudos,   // acumuladores de veces que se supera el lÃmite
      limBajos,limMedios,limAgudos;      // lÃmites calculados para cada canal




/*
* Funcion que aplica una ventana de Hann a los datos muestreados para reducir el
* efecto de las discontinuidades en los extremos
*/
void aplicaVentana (char *vData) {
    double muestrasMenosUno = (double(MUESTRAS) - 1.0);
  // Como la ventana es simétrica , se calcula para la mitad y se aplica el factor por los dos extremos
    for (uint8_t i = 0; i < MUESTRAS/2 ; i++) {
        double indiceMenosUno = double(i);
        double ratio = (indiceMenosUno / muestrasMenosUno);
        double factorPeso = 0.5 * (1.0 - cos(6.28 * ratio));
  vData[i] *= factorPeso;
  vData[MUESTRAS - (i + 1)] *= factorPeso;
    }
}


void setup() {           
    Serial.begin(9600);


    // Variables para el cálculo de los lÃmites
    pasada = 0;
    acumBajos = acumMedios = acumAgudos = 0;
    limBajos = limMedios = limAgudos = 50;
}


void loop() {

    // Realizamos el muestreo
    for( int i=0; i < MUESTRAS; i++) {
   im[i] = 0;                    // parte imaginaria = 0
    }

    Serial.println(" samples\n");
    for( int i=0; i < MUESTRAS; i++) {
      Serial.print(data[i], DEC);
      Serial.print(",");
    }
    Serial.println(" ---");

    // Aplicamos la ventana de Hann
    aplicaVentana (data);
    Serial.println(" window\n");
    for( int i=0; i < MUESTRAS; i++) {
      Serial.print(data[i], DEC);
      Serial.print(",");
    }
    Serial.println(" ---");

    // Calculamos la FFT
    fix_fft(data,im,LOGM,0);

    // Sólo nos interesan los valores absolutos, no las fases, asi que
    // calculamos el módulos de los vectores re*re + im*im.
    // Dado que los valores son pequeños utilizamos el cuadrado
    for (int i=0; i < MUESTRAS/2; i++){
       salida[i] = data[i] * data[i] + im[i] * im[i];
    }

    Serial.println(" result²²\n");
     for( int i=0; i < MUESTRAS/2; i++) {
      Serial.print(salida[i], DEC);
      Serial.print(",");
    }
    Serial.println(" ---");

}

 


SAMA5D4:

/*
* main.cpp
*
*  Created on: May 16, 2015
*      Author: Jan
*


*
*
*/


#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <math.h>
#include "fix_fft.h"
#include "unistd.h"


using namespace std;


#define MUESTRAS 128
#define LOGM 7                 // Logaritmo en hige 2 del número de muestras


#define BAJOS_MEDIOS 7         // Nº de banda para el corte entre Bajos y Medios
#define MEDIOS_AGUDOS 35       // Nº de banda para el corte entre Medios y Agudos


int data[MUESTRAS] = {0,7,14,21,28,35,42,49,56,63,70,77,84,91,98,105,112,119,126,-123,-116,-109,-102,-95,-88,-81,-74,-67,-60,-53,-46,-39,-32,-25,-18,-11,-4,3,10,17,24,31,38,45,52,59,66,73,80,87,94,101,108,115,122,-127,-120,-113,-106,-99,-92,-85,-78,-71,-64,-57,-50,-43,-36,-29,-22,-15,-8,-1,6,13,20,27,34,41,48,55,62,69,76,83,90,97,104,111,118,125,-124,-117,-110,-103,-96,-89,-82,-75,-68,-61,-54,-47,-40,-33,-26,-19,-12,-5,2,9,16,23,30,37,44,51,58,65,72,79,86,93,100,107,114,121};           // Array con los valores muestreados (parte real)
int im[MUESTRAS];             // Array con los valores muestreados (parte imaginaria)


#define MAX_PASADAS 10         // Nº de pasadas para el cálculo de los lÃmites


unsigned int salida[MUESTRAS/2];  // Valores obtenidos de la FFT (espectro de 64 bandas)
unsigned int bajos,medios,agudos; // Valores calculados para cada canal


uint  pasada,                            // nº de pasada para el cáculo de los lÃmites
      acumBajos,acumMedios,acumAgudos,   // acumuladores de veces que se supera el lÃmite
      limBajos,limMedios,limAgudos;      // lÃmites calculados para cada canal






int toint(std::string s)
{
    return atoi(s.c_str());
}




/*
* Funcion que aplica una ventana de Hann a los datos muestreados para reducir el
* efecto de las discontinuidades en los extremos
*/
void aplicaVentana (int *vData) {
    double muestrasMenosUno = (double(MUESTRAS) - 1.0);
  // Como la ventana es simétrica , se calcula para la mitad y se aplica el factor por los dos extremos
    for (int i = 0; i < MUESTRAS/2 ; i++) {
        double indiceMenosUno = double(i);
        double ratio = (indiceMenosUno / muestrasMenosUno);
        double factorPeso = 0.5 * (1.0 - cos(6.28 * ratio));
  vData[i] *= factorPeso;
  vData[MUESTRAS - (i + 1)] *= factorPeso;
    }
}


int main() {
  string line;
  int i = 0;








  while(1) {
    // get samples




    for( i=0; i < MUESTRAS; i++) {


//        data[i] = i*14-128;  //Convertimos de 0..1024 a -128..127
      im[i] = 0;                    // parte imaginaria = 0




    }


    cout << "\nsamples :\n";
    for( i=0; i < MUESTRAS; i++) {
      cout << data[i] << ",";
    }
    cout << "\n";






    // Aplicamos la ventana de Hann
    aplicaVentana (data);


    cout << "\nwindow :\n";
    for( i=0; i < MUESTRAS; i++) {
      cout << data[i] << ",";
    }
    cout << "\n";




    // Calculamos la FFT
    fix_fft(data,im,LOGM,0);






    // Sólo nos interesan los valores absolutos, no las fases, asi que
    // calculamos el módulos de los vectores re*re + im*im.
    // Dado que los valores son pequeños utilizamos el cuadrado
    for (i=0; i < MUESTRAS/2; i++){
       salida[i] = data[i] * data[i] + im[i] * im[i];
    }




    cout << "\nresults :\n";
    for( i=0; i < MUESTRAS/2; i++) {
      cout << salida[i] << ","; // this was the biggest mistake. I had a '1' where I should have put an 'i', hard to spot the difference
    }
    cout << "\n";


    break;  // this MUST be removed!!!!!!!!!!!!!!!!!!!!!!!!!!!

  }
  return 0;
}

 

 

 

Table of Contents
Chapter 1: Fix the turntable
1: Perpetuum Ebner Musical 1
2: A Time to Kill and a Time to Heal
3: Preparation for Motor Drive
4: Motor control with Infineon Motor Shield and Arduino UNO
5: Turntable speed sample testbed with Arduino UNO
6: Turntable Speed Sensor design
7: Control Theory - End of Chapter 1
Chapter 2: First Enchantments
8: Digital Light Organ Enchantment
9: Autonomous Servo Lift
10: SMD Time - Solder the IR Speed Sensor PCB
11: Yelp - who can Help me to Compile and Run my First SAMA5D4 C Program
12: Son et Lumiere - End of Chapter 2
Chapter 3: Taming the Board
13: Breakthrough - Run my own C++ Program on the SAMA5D4
14: Digital Light Organ Input Buffer
15: SAMA5D4 Blinky
16: Scope Creep
17: Audio Sampling with 16-bit ADC ADS8343
18: Sending Files to SAMA5D4 over USB
19: Port my Light Organ from Arduino to SAMA5D4
20: Fast Fourier Transform on the SAMA5D4 - End of Chapter 3
Epilogue: Reaching for the Clouds
21: Right-Sizing my Plans
22: My Own C++ Buffered Sampler on the SAMA5D4
Interlude
23: Building In the Motorized Light Organ
24: Up to the Clouds with Yún
25: Publish or Perish
26: Turntable Finished
Stretch & Boni
Bonus 1a: Remote Light Organ with WiFI pt. 1
Bonus 1b: Remote Light Organ with WiFI pt. 2
Grande Finale: Paho MQTT Client on the SAMA5D4
Related blog
Vintage Turntable repair: Can I fix a Perpetuum Ebner from 1958
Review 1: Atmel SMART SAMA5D4 Xplained Ultra Unboxing and First Steps
Review 2: Atmel SMART SAMA5D4 Xplained Ultra - Building the Libraries from Source
Review 3: Digital Continuous Rotation (360°) Servo Part 1
Review 4: Digital Continuous Rotation (360°) Servo Part 2
Review 5: Atmel SMART SAMA5D4 Xplained Ultra - TCP/IP running
Review 6: Atmel SMART SAMA5D4 Xplained Ultra - LINUX Distro with SSH support
poem
Enchanted Objects: Let's work together to tame the ATMEL SMART SAMA5D4 Xplained Ultra kit
17 bis: Off South...
Review 7: Atmel SMART SAMA5D4 Xplained Ultra - C++ ADC Example on Linux
Review 8: Atmel SMART SAMA5D4 Xplained Ultra - Product Review
Review 9a: Atmel SMART SAMA5D4 Xplained Ultra - Set up ADC Buffer with Hardware Trigger Part 1
Review 9b: Atmel SMART SAMA5D4 Xplained Ultra - Set up ADC Buffer with Hardware Trigger Part 2
Review 10: Atmel SMART SAMA5D4 Xplained Ultra - New Content on AT91.com
1958 Turntable from the Black Forest - Summary of the Enchanted Player Story
Attachments:
debuglog.txt.zip
debuglog2.txt.zip
  • Sign in to reply

Top Comments

  • Jan Cumps
    Jan Cumps over 10 years ago in reply to Workshopshed +2
    My biggest mistake was an extremely silly one: I had cout << salida[ 1 ] instead of cout << salida[i] . So the console always showed the second element of the array. And that's a one. 4 hours of debugging…
  • Jan Cumps
    Jan Cumps over 10 years ago in reply to Workshopshed +1
    I'm a little closer. I know that my lookups are good. The FFT does the same calcs and lookups in Arduino and SAMA5D4. It seems that the issue is with returning the resulting array:
  • Workshopshed
    Workshopshed over 10 years ago in reply to Jan Cumps +1
    Do you normally program in Spanish?
  • Workshopshed
    Workshopshed over 10 years ago in reply to Jan Cumps

    April seems so long ago...

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 10 years ago in reply to Workshopshed

    No image

    THe original source for the Light Organ is an Arduino sketch that I used unchanged in my project: 1958 Turntable from the Black Forest - 8: Digital Light Organ Enchantment

     

    Now that I'm porting it to the SAMA5D4, I leave as much of the code untouched.

    That makes it easier to compare the working Arduino version and the WIP SAMA... Version.

    ANd I can read Spanish image, so no issue for @self.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Workshopshed
    Workshopshed over 10 years ago in reply to Jan Cumps

    Do you normally program in Spanish?

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 10 years ago in reply to Workshopshed

    My biggest mistake was an extremely silly one:

     

    I had cout << salida[1]  instead of cout << salida[i]. So the console always showed the second element of the array. And that's a one.

    4 hours of debugging before I spotted it.

     

    I found some other smaller issues - related to switching from char to int - while digging deep inside the fft lib. So it was not for nothing.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 10 years ago in reply to Jan Cumps

    Success !!

     

    image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube