Design and organization are the really tricky part of software development. While small projects work well without it, they never live long nor can they be extended in a easy way. This is especially true if your resources are limited.
The software of this project has to overcome some limitations of the hardware. I planed playing samples at 22.1kHz, which is feasible using a controller running at 16MHz. The really tricky part was simultaneously accessing the SD-Card while writing the samples to the DAC.
While there are many libraries out there to access SD-Cards, even read and write FAT file systems, none of them had the required simple timing necessary to stream large amounts of data to the DAC. Therefore I wrote a class which is optimized for simple and fast SD-Card access. I will explain this class later in detail.
Most libraries I found reading the files from a FAT-16 or FAT-32 file system. This is comfortable for the user, because he can simple copy files from his computer to the SD-Card, but at the end it is unnecessary complex to have a FAT file system on the SD-Card if your only goal is to stream some data from it.
A minimal file system.I solved this by creating a very simple own “file system”, which just allows to have a number of files with a defined name copied on the card. To make things simple, I write a script, which converts a directory with some files in it, into a special image file which I can simply copy on the SD-Card. I will explain this simple file system and the script to create it later in more detail.
All other parts are encapsulated into own classes like a class to handle the sensor, a class to access the DAC and even one to control the status LED. There are also some small helper classes for timing.
Keep things as simple as possible.I kept everything as simple as possible, therefore I do not use interrupts which are simple not necessary to create the software for this device. Because software development for the Arduino platform was quite new to me, I had a look in so many other projects and source codes to see how things are done. But because I have more than 20 year experience in software development, especially in C++, I was a little disturbed how slovenly most code was written. Often it has no structure, with an unnecessary overuse of macros and looked like throw away code, written once to use once and forget. I hope to show that this is not really necessary, good and fast code do not have to look like an unstructured mess.
In the next pages I will first explain the interface of the class, how to use it, and second how everything is implemented. If you are only interested how to use the class, copy it, read the into and use it.
- Fast access to the SD-card with the
SDCard
class. (Part 2, Part 3) - Writing to the digital-analog converter with the
DacPort
class. - Play Audio using the
AudioPlayer
. - How to handle
loop()
without delays. - Time events with the
Timer
class. - Measure elapsing time using the
TimeDelta
class. - Controlling the status LED using the
LEDController
. - Accessing the motion sensor with the
MotionSensor
class. - Combine everything.
Where to get the Source Code
You will find all source code of the prototype on GitHub at this location:
https://github.com/LuckyResistor/CatProtect
While it is possible I already published further development of this software, I marked the version I discuss on this pages with the tag v1.0
. You can jump directly to this release using this URL:
https://github.com/LuckyResistor/CatProtect/releases/tag/v1.0
There you can download the version of the source code discussed on this pages.
Continue here: Access the SD-Card
sorry for my english but where you describe in the code which pin you used to connect with arduino to DAC,motion sensor etc… ????
You find this definitions in the header of various components of the software. E.g. in “
LEDController.h
” there is a constant calledRED_STATUS_PIN
which defines the pin where the red status LED is connected. The pins of the DAC are defined in the file “DacPort.cpp
”. But they are defined with the bit number and port of the microcontroller, but you find a description of the pin mapping the the header file. The pin of the sensor is defined in the “MotionSensor.h
” file, as constant “MOTION_SENSOR
”. It is set to analog pin 0. You will also find more information about the pin mapping the the schema, where you see “D0…D13” for the digital in/out pins and “A0…A5” for the analog pins.Do i have to change anything in your code about LED ? Because when I upload a code to Arduino it starts blinking red color and nothing happens, so i don’t is it my fault because I made a mistake connecting something or I must change something in code ?
If there is an error, the LED blinks red. If the device is waiting for the sensor, the LED blinks orange. If the project is ready, the LED flashes (very short and slow) green, or red if there was an event.
To get more information, use the serial monitor while the Arduino environment is connected to the board. Set the monitor to 115200 baud and you will get useful information about the problem.
You can get even more information if you uncomment the “#define XXXX_DEBUG” lines and recompile the code. While these lines are uncommented (remove the trailing // characters), you get lots of information in the serial monitor – but – the project wont work properly because of the slowdown from the serial. But you can use them to get more information about a possible problem.
Hmmm….still something wrong…”Error on initialize.” You see my shield is using digital pin 4, so DAC_SDI is now Connected to Digital pin 8. I changed in code pinMode to 8 and #define DAC_DI_PORT PORTD
#define DAC_DI PIND4
to
#define DAC_DI_PORT PORTB
#define DAC_DI PINB0
because in pin map digital 8 is PB0 port
Maye it has something to do with that ?
“Error on initialize.” is coming from the audio player. Uncomment the “#define AUDIOPLAYER_DEBUG” line in the “AudioPlayer.h” file and recompile to get more information about the problem.
Still same. Maybe it is because SD CARD is empty ?
Did you uncomment the line? Do you know what I mean with “uncomment the ‘#define AUDIOPLAYER_DEBUG’ line”? It will give you a detailed answer where the problem is.
I’m sorry. My mistake i thought it meant to delete that line. Now show this:
Starting…
SD Card Init Success.
SD Card read directory failure, error=7
Error on initialize.
Error 7 = Unknown Magic. That means everything is working so far, but the SD card does not has the required image on it. After you prepare the SD card with the audio files, the audio player should work. Explained here: http://luckyresistor.me/2015/11/24/how-to-use-the-scripts-in-the-cat-protector-project/
OK. I’ll try when i upload an image to SD CARD. Thank you !
Starting…
Success!
Wait until the sensor is ready.
Sensor is in idle state.
Sensor alarm.
Error on play.
then goes back to “Sensor is in idle state.”
Almost there. Now have a look in the “CatProtect.ino” file at line 45. Here you have to provide a list of the filenames of your samples. Replace the list with the names of your sample files you used to create the SD card image. Or alternatively, create a new image and use the shown names.
In your example it is named voice.snd ? I tried to change it to my samples name. It was OriginalSound01.wav
Error is gone but sound doesn’t play AND sensor doesn’t go back to idle state
For a test you can download this example image: https://luckyresistor.files.wordpress.com/2015/12/diskimage3-img1.zip
It contains the samples “v0.snd”, “v1.snd” and “v2.snd” with valid test sounds for the project. Try this image to make sure it is not a problem with your samples. Next start testing your project using e.g. a osscilloscope if you have one available. First check if the DAC gets the digital signals and then check the DAC output and last check the amplifier output.
Nope. DAC doesn’t show any signs on osciloscope. But I dont understand why. I tested DAC with this code and it worked fine. P.s I’m using not ADAFRUIT shield, but this one http://wiki.iteadstudio.com/Stackable_SD_Card_shield_V3.0
Seems you need to do some systematic tests. Rewrite the code and write some DAC test. Finding issues and problems usually takes the most time in such projects. Ask someone else to have a look, often with a second pair of eyes you will find the problem faster.
Sorry, last time URL didn’t copy about testing DAC. So I meant that I tested DAC with this code https://github.com/fisitronics/ArduinoLibraries/blob/master/MCP4821/DAC_MCP4821/Examples/TestDACMCP4821/TestDACMCP4821.ino I checked with osciloscope and it worked fine. But when i run CatProtect code – signal is gone. Maybe i should change pins between DAC and Arduino ?
For the original circuit, CS is connected to digital pin 2, SCK to pin 3, SDI to pin 4 and LDAC to pin 5. This is necessary, because the SD card from the shield uses pin 10, 11, 12 and 13 and the software writes to the DAC while reading from the SD card.
Well that’s a problem, because my sd card shield uses 11, 12, 13 and 4 pins, not 10th. My shield PinMap is here: http://wiki.iteadstudio.com/Stackable_SD_Card_shield_V3.0
So please tell what do i have to change in code exactly if want to change DAC SDI pin 4 to pin 8 ???
BTW I presume you didn’t check my shield pinmap in URL I pasted about shield I’m using. I think i have to change ports in code SDCard.cpp
My SDCard code is using the SPI port of the microcontroller, so pins 11, 12 and 13 can not be changed. Your shield seems to use digital pin 4 as chip select, not 10. Because my project is using pin 4 for the DAC, this is likely the cause why the DAC is not working in your project.
You can change the pin for the chip select in file “SDCard.cpp” in lines 20, 21 and 22. You have to adjust all three lines. In the first line you have to set the port to 4, and in line 21 and 22 you have to set the right port and mask for pin 4.
The DAC should in this can _not_ use pin 4 obviously, because it is connected to the SD card. You can just connect the DAC data pin with digital pin 10 of the microcontroller and adjust the pins in the DAC code.
Best you draw a connection plan on a paper and systematically check what is connected to which pins and if there are no conflicts. Then change the code to match your connection plan.
Sorry I can not spend more time supporting your project. Best if you search some local help with a bit more experience in electronics. You are currently on a good way with your project. I hope you will get it running soon.
Well, still nothing. Anyway you already helped me alot. Thank you for that. Really. I’ll try to figure out the rest myseslf. But one last question: Does it have something to do with my speaker, because it has 32 ohms and I connected it with 5V from Arduino ?
At least you should get some noise out of it. And you can always use the oscilloscope to check if you get any output from the DAC at all. But the impedance of the speaker affects other parameters of the amp, the output of the amp could be way to much for the speaker. Also I would strongly advise you to connect the amp directly to the 9V of the power source. The amp is drawing a lot of current, and this could be too much for the microcontroller circuit.
I know you are busy but even very experienced firends in electronics have no clue what is wrong. I’m sure it’s not A problem with schematics and components. Only problem it can be it is the code. Are you sure your code is working in project ? Because I even cut the traces of pin 4 and connected to pin 10 In order that i won’t need to change anything in your code but still same problem. Serial monitor writes “sensor alarm” and stays that way always. And whcich Arduino IDE version you used ? 1.0.x ? 1.5.x ?
I am using the Arduino IDE version 1.5.x to compile the code. And I am sure there is nothing wrong with the code, because I built the device with exactly this code and it is working fine.
It is possible to exactly locate the problem with a systematic analysis. You will not find the problem with trial and error. You have to locate which component is not working and then search for the origin of the problem. You are using different hardware as I did, so I can not guarantee that the code I wrote is working on this different hardware. Nevertheless it should be possible to locate the exact problem with a systematic analysis.
You can also add additional serial output lines in the code to check if a certain part of the code is executed. You can also use the oscilloscope to check if you have the correct signals at the outputs of the microcontroller and of the components. But in engineering it is crucial to have a plan how and what to test, in which order, and do this in a systematic way. Also what to expect from the test and what insights you gain from the result.
– Check which parts/components are working as expected.
– Check which parts/components are not working as expected.
– Search for the reason why the are not working as expected and fix the problem.
– Repeat until everything is working.
I need to draw a program algorithm. Maybe you have one or can tell me what’s the alogrthm of this program code ?
You can draw it as a “state machine”, it will represent the functionality of the code better than an algorithm. You find the states in the enum called “LogicState” in the file “CatProtect.ino”. Now there are certain events when the code switches between this states.