Swap
Swap

Reputation: 11

How to Record Calls to an SD Card using AT Commands with SIM800C GSM Module and Arduino UNO?

Im working on a project using an Arduino Uno and a SIM800C GSM module where I need to record phone calls directly to an external SD card. However, I'm unsure which AT commands to use and how to configure the setup for this functionality. The SIM800C documentation hasn't provided clear instructions on how to achieve this.

What I Need:

  1. AT commands that support starting, stopping, and managing call recording to an SD card.
  2. Command sequence and steps required to correctly initiate and manage call recording during an active call, and ensure it's saved to the SD card.
  3. Any example code or detailed steps that could guide me in implementing this functionality.

What I've Tried: I've successfully initiated and answered calls with the following AT commands:

  1. ATD+;
  2. AT+CREC - Results In ERROR, I suspect that either the command is incorrect or additional steps are required.

Questions:

  1. What are the correct AT commands to record a call and save it to an external SD card using the SIM800C module?
  2. Is there a specific sequence or additional setup needed to achieve this?
  3. Can anyone provide a working example or detailed instructions on how to implement call recording to an SD card with this module?
  4. Any guidance or example code would be greatly appreciated. Thank you!

Code i have tried,

`#include <SoftwareSerial.h>
 #include <SD.h>
 #include <SPI.h>

 const int chipSelect = 10; // GPIO pin connected to the SD card CS pin
 const int sim800Tx = 2;   // TX pin of SIM800C
 const int sim800Rx = 3;   // RX pin of SIM800C
 const int sim800Reset = 9; // Reset pin of SIM800C

 SoftwareSerial sim800(sim800Rx, sim800Tx);
 File audioFile;

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

   pinMode(sim800Reset, OUTPUT);
   digitalWrite(sim800Reset, HIGH);

   // Initialize SD card
   if (!SD.begin(chipSelect)) {
     Serial.println("Initialization of SD card failed!");
     return;
   }

   Serial.println("SD card initialized.");

   // Reset SIM800C
   resetSIM800();

   // Wait for network registration
   waitForNetwork();

   // Set the SIM800C to automatically answer calls after 2 rings
   sim800.println("ATS0=1");
   delay(1000);
 }

 void loop() {
   if (sim800.available()) {
     String callStatus = sim800.readString();

     // Check if the call is received
     if (callStatus.indexOf("RING") != -1) {
       Serial.println("Incoming call...");
       delay(2000); // Wait for 2 seconds to ensure the call is answered automatically
       startRecording();
     }

     // Check if the call is disconnected
     if (callStatus.indexOf("NO CARRIER") != -1 ||      callStatus.indexOf("BUSY") != -1) {
       Serial.println("Call ended.");
       stopRecording();
     }
   }
 }

 void resetSIM800() {
   digitalWrite(sim800Reset, LOW);
   delay(1000);
   digitalWrite(sim800Reset, HIGH);
   delay(1000);
 }

 void waitForNetwork() {
   while (true) {
     sim800.println("AT+CREG?");
     delay(1000);
     if (sim800.find("+CREG: 0,1")) {
       Serial.println("Network registered.");
       break;
     } else {
       Serial.println("Waiting for network...");
     }
   }
 }

 void startRecording() {
   // Create a new WAV file on the SD card
   audioFile = SD.open("/record.wav", FILE_WRITE);

   if (!audioFile) {
     Serial.println("Failed to open file on SD card!");
     return;
   }

   // Write the WAV header (with placeholder sizes)
   writeWavHeader();

   Serial.println("Starting recording...");

   // Send the CREC command to start recording
   sim800.println("AT+CREC=1,\"C:\\RECORD.AMR\",0");
   delay(1000);
   
   if (sim800.find("OK")) {
     Serial.println("Recording started.");
   } else {
     Serial.println("Failed to start recording.");
   }
 }

 void stopRecording() {
   Serial.println("Stopping recording...");

   // Send the CREC command to stop recording
   sim800.println("AT+CREC=2");
   delay(1000);

   if (sim800.find("OK")) {
     Serial.println("Recording stopped.");
     appendRecordingToWav();
     updateWavHeader();
   } else {
     Serial.println("Failed to stop recording.");
   }
 }

 void writeWavHeader() {
   uint32_t sampleRate = 8000; // Adjust based on actual rate used by AMR
   uint16_t numChannels = 1;   // Mono audio
   uint16_t bitsPerSample = 16;
   uint32_t byteRate = sampleRate * numChannels *      (bitsPerSample / 8);

   audioFile.write("RIFF", 4);
   audioFile.write((uint8_t*)"\0\0\0\0", 4); // Placeholder      for file size
   audioFile.write("WAVE", 4);
   audioFile.write("fmt ", 4);
   audioFile.write((uint8_t*)"\x10\0\0\0", 4); //      Subchunk1Size
   audioFile.write((uint8_t*)"\x01\0", 2);     // AudioFormat (1 for PCM)
   audioFile.write((uint8_t*)&numChannels, 2);
   audioFile.write((uint8_t*)&sampleRate, 4);
   audioFile.write((uint8_t*)&byteRate, 4);
   audioFile.write((uint8_t*)(2 * numChannels), 2); // BlockAlign
   audioFile.write((uint8_t*)&bitsPerSample, 2);
   audioFile.write("data", 4);
   audioFile.write((uint8_t*)"\0\0\0\0", 4); // Placeholder for data chunk size
 }

 void updateWavHeader() {
   uint32_t fileSize = audioFile.size();
   uint32_t dataChunkSize = fileSize - 44;

   audioFile.seek(4);
   audioFile.write((uint8_t*)&fileSize, 4);
   audioFile.seek(40);
   audioFile.write((uint8_t*)&dataChunkSize, 4);

   Serial.println("WAV header updated.");
 }

 void appendRecordingToWav() {
   // Read the recorded AMR file from the SIM800C and convert to PCM
   sim800.println("AT+FSREAD=\"C:/RECORD.AMR\",0");
   delay(1000);

   // Simulate the conversion of AMR to PCM data and write it to the WAV file
   while (sim800.available()) {
     char c = sim800.read();
     // Here we would convert AMR data to PCM; for simplicity, we write it directly
     audioFile.write(c);
   }

   audioFile.close();
   Serial.println("Recording saved as WAV to SD card.");
 }`

Upvotes: 0

Views: 117

Answers (0)

Related Questions