Hi all! I have an old project that used Teensy 3.2 + Audio Board that I try since a couple of days to update to the new 4.0 versions. I've read the great summary from Michael: https://forum.pjrc.com/index.php?threads/porting-from-teensy-3-2-to-4-0.71710/ and performed the pin changes according with the new references, however I keep on having the same error in my output console "Compilation error: exit status 1". I'm using Arduino 2.3.2 on macOS 14.5. I also tried the 1.8 Arduino version with Teensyduino support and the error is "Error compiling for board Teensy 4.0." Other codes seem to compile fine on the 4.0, except mine Maybe someone has an idea?
here the code, apologies in advance for the many notes
thanks!
here the code, apologies in advance for the many notes
thanks!
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h> // new added 9.24
#include <CapacitiveSensor.h> // added for Teensy 4.0 because there is no more "Pin_touch" inbuild
// define all the stuff
const char *mainTrack = "011.WAV";
#define PIN_LEDS A3
#define VAL_LED_MAX 4095
#define PIN_LED_ONBOARD 13
#define PIN_VIBMOTOR 5
#define PIN_BUTTON_IN 4
#define PIN_VOLTAGE_SEN A3
#define PIN_EXTRA A6
CapacitiveSensor cs_3_2 = CapacitiveSensor(4,2); // 10M resistor between pins 4 & 2, pin 2 is sensor pin, add a wire and or foil if desired
CapacitiveSensor cs_3_1 = CapacitiveSensor(4,1); // 10M resistor between pins 4 & 6, pin 6 is sensor pin, add a wire and or foil
CapacitiveSensor cs_3_0 = CapacitiveSensor(3,0); // 10M resistor between pins 4 & 8, pin 8 is sensor pin, add a wire and or foil
// GUItool: begin automatically generated code
AudioPlaySdWav playSdWav3; //
AudioPlaySdWav playSdWav2; //xy=122,176
AudioInputI2S i2s2; //xy=122,234
AudioPlaySdWav playSdWav1; //xy=123,132
AudioMixer4 mixer2; //xy=468,227
AudioMixer4 mixer1; //xy=469,146
AudioOutputI2S i2s1; //xy=642,186
AudioConnection patchCord9(playSdWav3, 0, mixer1, 2);
AudioConnection patchCord10(playSdWav3, 1, mixer2, 2);
AudioConnection patchCord1(playSdWav2, 0, mixer1, 1);
AudioConnection patchCord2(playSdWav2, 1, mixer2, 1);
AudioConnection patchCord3(i2s2, 0, mixer1, 2); //simultaniuos playback and crosfade works when
AudioConnection patchCord4(i2s2, 1, mixer2, 2); //this two lines are commented
AudioConnection patchCord5(playSdWav1, 0, mixer1, 0);
AudioConnection patchCord6(playSdWav1, 1, mixer2, 0);
AudioConnection patchCord7(mixer2, 0, i2s1, 1);
AudioConnection patchCord8(mixer1, 0, i2s1, 0);
AudioControlSGTL5000 sgtl5000_1; //xy=126,46
// GUItool: end automatically generated code
#define NUM_IDLESEQENSE 50
// The Data Structor to store Program/Case ID and the Time Value
typedef struct IdleSeqense_struct
{
unsigned int CaseID;
unsigned int TimeOut;
};
// Here we store the IdleModeSequense
IdleSeqense_struct IdleSeqense[NUM_IDLESEQENSE] = {{6, 15000}, {3, 7500}, {7, 15000}, {3, 7500}, {5, 15000}, {3, 10000}, {4, 10000}, {7, 10000}, {3, 10000}, {5, 5000}, {3, 15000}, {2, 5000}, {7, 10000}, {2, 5000}, {3, 5000}, {2, 10000}, {3, 1000}, {7, 7000}, {3, 2000}, {2, 5000}, {3, 2000}, {2, 10000}, {0, 2000}, {2, 10000}, {7, 15000}, {2, 7000}, {0, 2000}, {2, 5000}, {1, 10000}, {7, 5000}, {0, 10000}, {3, 5000}, {1, 7500}, {3, 5000}, {7, 10000}, {5, 5000}, {1, 7000}, {6, 5000}, {4, 15000}, {7, 5000}, {6, 15000}, {4, 10000}, {7, 5000}, {5, 5000}, {7, 5000}, {4, 5000}, {6, 15000}, {4, 5000}, {7, 5000}, {6, 15000}};
// This is our index cursor to keep track where we are in the sequense
char IdleSeqenseCursor = 0;
// Here we store if the idle its in the idle mode
bool IdleMode = false;
// The time out value how much 'no input' is needed to start the Idle Sequense
unsigned long IdleTimeOut = 10;
void setGain(int source, float gain)
{
mixer1.gain(source, gain);
mixer2.gain(source, gain);
}
const unsigned long motorDuration = 3000; // Duration in milliseconds (3 seconds)
unsigned long motorStartTime = 0;
int currentMode = 0; // Initialize mode to 0 initially
void setup()
{
/* add setup code here */
analogWriteResolution(12);
//pinMode(PIN_LEDS,OUTPUT);
pinMode(PIN_LED_ONBOARD, OUTPUT);
pinMode(PIN_VIBMOTOR, OUTPUT);
digitalWrite(PIN_VIBMOTOR, LOW);
cs_3_2.set_CS_AutocaL_Millis(0xFFFFFFFF); // turn off autocalibrate on channel 1 - just as an example
//SetSensorOffset();
Serial.begin(115200);
///AUtio Setup
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(18);// if its not working use less 15 or 10
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
SPI.setMOSI(11); // (7) in 3.3 version
SPI.setSCK(13); // (14) in 3.3 version
if (!(SD.begin(10))) {
// stop here, but print a message repetitively
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
setGain(0, 0.5f);
setGain(1, 0.0f);
setGain(2, 0.5f);
setupAudioPool();
}
unsigned int delayOn[] = {500 /* 1 Hz*/, 500 / 2 /* 2 Hz*/, 500 / 5 /* 5 Hz*/, 500 / 10 /* 10 Hz*/, 500 / 15 /* 15 Hz*/, 500 / 20 /* 20 Hz*/, 500 / 25 /* 25 Hz*/, (500 / 30) + 1 /* 30 Hz*/, 500/*1Hz+sound1*/, 500/*1Hz+sound2*/};
unsigned long blinkCounter = 0;
/*
case 0= 1Hz
case 1= 2Hz
case 2= 5Hz
case 3= 10Hz
case 4= 15Hz
case 5= 20Hz
case 6= 25Hz
case 7= 30Hz
case 8= 1Hz + sound 1
case 9= 1Hz + sound 2
*/
bool isBlinkingOn = true;
void loop()
{
long start = millis();
long total1 = cs_3_2.capacitiveSensor(30);
long total2 = cs_3_1.capacitiveSensor(30);
long total3 = cs_3_0.capacitiveSensor(30);
static int dir = 1;
static int Mode = 0;
static bool VibMotorOn = false;
/* add main program code here */
static bool IdleTimeOutStarted = false;
static unsigned long IdleTimeOutTimer = 0;
// This Just Switches Thur the >>>>>
loopTheBaseAudio();
static unsigned long tmpTime = millis() + 200;
// Read Inputs an check serial every 200 milli seconds (we dont want to spend a lot time there)
if (tmpTime < millis())
{
int Val1 = total1;
int Val2 = total2;
int Val3 = total3;
Serial.print(Val1, DEC);
Serial.print("\t");
Serial.print(Val2, DEC);
Serial.print("\t");
Serial.print(Val3, DEC);
Serial.print("\t");
Serial.println();
tmpTime += 200;
// AutoOffset();
// In TmpMode we store the previose Mode NOTE: its declared as static!
static int TmpMode = Mode;
// if we have no sensor input we switch into the idle mode after the time out (NOTE: Now Val is a negative value thats why its used as (-Val)
// else the direkt feedback switching should happen with the sensor data Val
if ((Val1 <= 5000) && (Val2 <= 5000) && (Val3 <= 5000))
{
VibMotorOn = false; // Added 9.12.2015
// if not in idle mode the start the timeout timer to get into idle mode
if (IdleMode == false)
{
// Start the timeou once
if (IdleTimeOutStarted == false)
{
// Yes
IdleTimeOutStarted = true;
// Calculate the timeOut time
IdleTimeOutTimer = millis() + IdleTimeOut;
// Reset cursor to start index
IdleSeqenseCursor = 0;
// Switch off the lights for now
isBlinkingOn = false;
// write a 0 to the constant current sources
digitalWrite(PIN_LEDS, 0);
Serial.println("Start Timout");
}
// Check if already enough timeout time has past the switch into the idle mode
if (IdleTimeOutTimer <= millis())
{
Serial.println("First time out");
isBlinkingOn = true;
IdleMode = true;
// set timing for first time out and switch into the correnct mode
IdleTimeOutTimer = IdleSeqense[0].TimeOut + millis();
Mode = IdleSeqense[0].CaseID;
IdleSeqenseCursor = 0;
// active IdleTimeOutStarted already for next time
IdleTimeOutStarted = false;
}
} else
{
isBlinkingOn = true;
// Idle Mode Sequense is here
if (IdleTimeOutTimer <= millis())
{
Serial.println("Switch time out1");
// Increase your cursor
IdleSeqenseCursor++;
// if the cursor is biiger then we have sequensens then we start from the biggining (round robin with modulo %)
IdleSeqenseCursor = IdleSeqenseCursor % NUM_IDLESEQENSE;
// Yes
IdleMode = true;
// set timing for first time out and switch into the correnct mode
IdleTimeOutTimer = IdleSeqense[IdleSeqenseCursor].TimeOut + millis();;
Mode = IdleSeqense[IdleSeqenseCursor].CaseID;
}
}
} else // Val input is bigger then 10
{
// we wanna blink
IdleMode = false;
IdleTimeOutStarted = false;
/// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int SensorMode = 0;
//>>>>> From the sensor input Val1 we deside now what to do
if ((Val1) > 5000)
{
SensorMode = 1;
}
//>>>>> From the sensor input Val2 we deside now what to do
if ((Val2) > 5000)
{
SensorMode = 2;
}
//>>>>> From the sensor input Val3 we deside now what to do
if ((Val3) > 5000)
{
SensorMode = 3;
}
switch (SensorMode)
{
case 0: // Idle Mode
IdleMode = true; Mode = 0; isBlinkingOn = false; VibMotorOn = false;
break;
case 1: // S1
Mode = 1; isBlinkingOn = true; VibMotorOn = false;
break;
case 2: // S2
Mode = 4; isBlinkingOn = true; VibMotorOn = false;
break;
case 3: // S3
Mode = 7; isBlinkingOn = true; VibMotorOn = true;
break;
}
/// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Here We just make sure our mode stayes in range (0-9)
if (Mode < 0) Mode = 0;
if (Mode >= 9) Mode = 9;
}
// if the Mode is different from the prior mode then we start the new audio feedback
if (TmpMode != Mode)
{
// Update previose state
TmpMode = Mode;
//sgtl5000_1.volume(0.0);
switch (Mode)
{
case 0:
playFilePool("001.WAV");
break;
case 1:
playFilePool("002.WAV");
break;
case 2:
playFilePool("003.WAV");
break;
case 3:
playFilePool("004.WAV");
break;
case 4:
playFilePool("005.WAV");
break;
case 5:
playFilePool("006.WAV");
break;
case 6:
playFilePool("007.WAV");
break;
case 7:
playFilePool("008.WAV");
Mode = 7; isBlinkingOn = true; VibMotorOn = true;
break;
case 8:
playFilePool("009.WAV");
break;
case 9:
playFilePool("010.WAV");
break;
default:
stopAudioPool();
break;
}
//sgtl5000_1.volume(0.5);
}
if (Mode == 7) {
VibMotorOn = true;
}
if (VibMotorOn)
{
//Serial.write("vib ius on");
// Here we could play with PWM our oulsing the motors too
digitalWrite(PIN_VIBMOTOR, HIGH);
} else
{
// switching the vibration motor off
digitalWrite(PIN_VIBMOTOR, LOW);
///stopAudio();
}
}
// <<<<
if (isBlinkingOn) DoBlinking(Mode, VAL_LED_MAX);
else stopAudio();
static long milNext = 0;
if (milNext < millis())
{
milNext = millis() + 5;
updateAudiMixer();
}
}
/// This Funktion hanles the time based freqeunse stwitching for the LEDs
/// Parameters are Mode .. do know which frequens Value ... is the brigthness of the LED (0 - 4068)
void DoBlinking(int Mode, int Value)
{
static int LEDState = 0;
if (blinkCounter < millis()) // Switch
{
switch (LEDState)
{
case 0:
LEDState = 1;
// Swtich ON
digitalWrite(PIN_LEDS, HIGH);
break;
default:
LEDState = 0;
digitalWrite(PIN_LEDS, LOW);
break;
}
blinkCounter += delayOn[Mode];
}
}
void stopAudio()
{
if (playSdWav1.isPlaying())playSdWav1.stop();
if (playSdWav2.isPlaying())playSdWav2.stop();
//if (playSdWav3.isPlaying())playSdWav3.stop();
}
struct Audio_pool_obj
{
char* audio_ch1_file = nullptr;
float gain = 0, fade_dir = 0;
AudioPlaySdWav* playSdWav = nullptr;
};
const int pool_size = 2;
Audio_pool_obj audio_pool[3];
float fade_step = 0.01;
void stopAudioPool()
{
for (int i = 0; i < pool_size; i++)
{
audio_pool[i].fade_dir = -fade_step;
}
}
void updateAudiMixer()
{
for (int i = 0; i < pool_size; i++)
{
if (audio_pool[i].audio_ch1_file == nullptr) continue;
audio_pool[i].gain += audio_pool[i].fade_dir;
if (audio_pool[i].gain >= 1)audio_pool[i].gain = 1;
if (audio_pool[i].gain <= 0)
{
audio_pool[i].gain = 0;
if (audio_pool[i].playSdWav->isPlaying())audio_pool[i].playSdWav->stop();
audio_pool[i].audio_ch1_file = nullptr;
}
setGain(i, audio_pool[i].gain);
}
}
void setupAudioPool()
{
audio_pool[0].playSdWav = &playSdWav1;
audio_pool[1].playSdWav = &playSdWav2;
audio_pool[2].playSdWav = &playSdWav3;
startBaseTracke();
}
void loopTheBaseAudio()
{
if( audio_pool[2].playSdWav->isPlaying())return;
startBaseTracke();
}
void startBaseTracke()
{
setGain(2, 1);
audio_pool[2].playSdWav->play(mainTrack);
delay(10);
}
bool started = false;
void playFilePool(const char *filename)
{
Serial.print("Playing file: ");
// find free pool and fade out others
bool found = false;
for (int i = 0; i < pool_size ; i++)
{
Serial.print("seARCH");
if (audio_pool[i].audio_ch1_file == nullptr && !found)
{
Serial.print("FOUND");
found = true;
audio_pool[i].playSdWav->play(filename);
Serial.print("Playing file: "); Serial.print(filename); Serial.print(" on "); Serial.println(i);
audio_pool[i].fade_dir = fade_step;
audio_pool[i].audio_ch1_file = filename;
} else
{
audio_pool[i].fade_dir = -fade_step;
}
}
}