upload/downlaod file from FTP using AT commands (Sim900 + arduino)

In the previous post I explained how to make a connection and send data via TCP connection on SIM900 and similar modems. This post is going to be about FTP connection. FTP stands for “file transfer protocol.” FTP powers one of the fundamental Internet functions and is the prescribed method for the transfer of files between computers. It is also the easiest and most secure way to exchange files over the Internet.

Without going into much details I would show the related AT commands and brief description. Later I would include sample code for FTP upload/download using arduino and SIM900

AT command Response Description
AT+SAPBR OK Configures GPRS profile.
AT+FTPCID=1 OK Selects profile 1 for FTP.
AT+FTPSERV=”****” OK Sets FTP server domain name or IP address. **** is the domain name or the IP.
AT+FTPPORT=*** OK Sets FTP server port. *** is the port.
AT+FTPUN=”***” OK Sets user name for FTP server access. *** is the user name.
AT+FTPPW=”***” OK Sets password for FTP server access. *** is the password.
AT+FTPPUTNAME=”****” OK Sets destiny name for the file.*** is the name of the file.
AT+FTPPUTPATH=”****” OK Sets destiny file path. *** is the path of the file.
AT+FTPPUT OK Use to put a file into the FTP server.
AT+FTPGETNAME=”****” OK Sets origin name for the file.*** is the name of the file.
AT+FTPGETPATH=”****” OK Sets origin file path. *** is the path of the file.
AT+FTPGET Use to get a file into the FTP server.

Make sure you have a server and note the ftp port, we would consider using the default port 21. Switch on your modem and make sure pin code is disabled or properly entered and that GPRS connection is available.

  1. Configure GPRS by sending AT+SAPBR=3,1,”Contype”,”GPRS”r  .
  2. Set APN by sending   AT+SAPBR=3,1,”APN”,”your apn”r  .replace your apn with APN for your network.
  3. Now set the username and password for the apn (replace username and password with correct values )
    AT+SAPBR=3,1,”USER”,”username”r  .
    AT+SAPBR=3,1,”PASS”,”password”r
  4. Connect to GPRS connection by sending AT+SAPBR=1,1r, when connected Modem will respond with OK
  5. Now select profile 1 for FTP by sending AT+FTPCID=1r
  6. Now set FTP server domain or ip using the command AT+FTPSERV=ftp.yourserver.comr
  7. Set FTP port by AT+FTPPORT=21r
  8. Now send FTP credentials using AT+FTPUN=user_namer and AT+FTPPW=”password”r
  9. To get a file from FTP send AT+FTPGETNAME=file_namer
  10.  Now set the path of the file AT+FTPGETPATH=/path/r
  11. Now send AT+FTPGET=1r and wait for response from server, which starts with +FTPGET:1,1
  12. To upload a file to FTP server send AT+FTPPUTNAME=file_namer
  13. Now set path AT+FTPPUTPATH=/pathr
  14. Now send AT+FTPPUT=1 and wait for +FTPPUT:1,1 after which you need to send the content of file to be uploaded.

int8_t answer;
int onModulePin = 2;
char aux_str[30];

char incoming_data[120];

char test_str[ ]= "0000000011111111222222223333333344444444555555556666666677777777000000001111111122222222333333334444";

int data_size, aux;


void setup(){

    pinMode(onModulePin, OUTPUT);
    Serial.begin(115200);


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

    delay(5000);

    Serial.println("Connecting to the network...");

    while( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500)
            || sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 );

    configure_FTP();

    uploadFTP();

    downloadFTP();

    Serial.print("Incoming data: ");
    Serial.println(incoming_data);
}


void loop(){

}


void configure_FTP(){

    sendATcommand("AT+SAPBR=3,1,"Contype","GPRS"", "OK", 2000);
    sendATcommand("AT+SAPBR=3,1,"APN","APN"", "OK", 2000);
    sendATcommand("AT+SAPBR=3,1,"USER","user_name"", "OK", 2000);
    sendATcommand("AT+SAPBR=3,1,"PWD","password"", "OK", 2000);

    while (sendATcommand("AT+SAPBR=1,1", "OK", 20000) != 1);
    sendATcommand("AT+FTPCID=1", "OK", 2000);
    sendATcommand("AT+FTPSERV="ftp.yourserver.com"", "OK", 2000);
    sendATcommand("AT+FTPPORT=21", "OK", 2000);
    sendATcommand("AT+FTPUN="user_name"", "OK", 2000);
    sendATcommand("AT+FTPPW="password"", "OK", 2000);

}


void uploadFTP(){

    sendATcommand("AT+FTPPUTNAME="file_name"", "OK", 2000);
    sendATcommand("AT+FTPPUTPATH="/path"", "OK", 2000);
    if (sendATcommand("AT+FTPPUT=1", "+FTPPUT:1,1,", 30000) == 1)
    {
        data_size = 0;
        while(Serial.available()==0);
        aux = Serial.read();
        do{
            data_size *= 10;
            data_size += (aux-0x30);
            while(Serial.available()==0);
            aux = Serial.read();
        }
        while(aux != 0x0D);

        if (data_size >= 100)
        {
            if (sendATcommand("AT+FTPPUT=2,100", "+FTPPUT:2,100", 30000) == 1)
            {
                Serial.println(sendATcommand(test_str, "+FTPPUT:1,1", 30000), DEC);
                Serial.println(sendATcommand("AT+FTPPUT=2,0", "+FTPPUT:1,0", 30000), DEC);
                Serial.println("Upload done!!");
            }
            else
            {
                sendATcommand("AT+FTPPUT=2,0", "OK", 30000);
            }
        }
        else
        {
            sendATcommand("AT+FTPPUT=2,0", "OK", 30000);
        }
    }
    else
    {
        Serial.println("Error openning the FTP session");
    }
}

void downloadFTP(){

    int x = 0;

    sendATcommand("AT+FTPGETNAME="file_name"", "OK", 2000);
    sendATcommand("AT+FTPGETPATH="/path"", "OK", 2000);
    if (sendATcommand("AT+FTPGET=1 ", "+FTPGET:1,1", 30000) == 1)
    {
        do{
            if (sendATcommand2("AT+FTPGET=2,50", "+FTPGET:2,", "+FTPGET:1,", 30000) == 1)
            {
                data_size = 0;
                while(Serial.available()==0);
                aux = Serial.read();
                do{
                    data_size *= 10;
                    data_size += (aux-0x30);
                    while(Serial.available()==0);
                    aux = Serial.read();
                }while(aux != 0x0D);

                Serial.print("Data received: ");
                Serial.println(data_size);

                if (data_size > 0)
                {
                    while(Serial.available() < data_size);
                    Serial.read();

                    for (int y = 0; y < data_size; y++)
                    {
                        incoming_data[x] = Serial.read();
                        x++;
                    }
                    incoming_data[x] = '';
                }
                else
                {
                    Serial.println("Download finished");
                }
            }
            else if (answer == 2)
            {
                Serial.println("Error from FTP");
            }
            else
            {
                Serial.println("Error getting the file");
                data_size = 0;
            }
        }while (data_size > 0);
    }
    else
    {
        Serial.println("Error openning the FTP session");
    }
}




void power_on(){

    uint8_t answer=0;

    // checks if the module is started
    answer = sendATcommand("AT", "OK", 2000);
    if (answer == 0)
    {
        digitalWrite(onModulePin,HIGH);
        delay(3000);
        digitalWrite(onModulePin,LOW);

        while(answer == 0){     // Send AT every two seconds and wait for the answer
            answer = sendATcommand("AT", "OK", 2000);
        }
    }
}


int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout){

    uint8_t x=0,  answer=0;
    char response[100];
    unsigned long previous;

    memset(response, '', 100);    // Initialize the string

    delay(100);

    while( Serial.available() > 0) Serial.read();    // Clean the input buffer

    Serial.println(ATcommand);    // Send the AT command


        x = 0;
    previous = millis();

    // this loop waits for the answer
    do{
        if(Serial.available() != 0){
            // if there are data in the UART input buffer, reads it and checks for the asnwer
            response[x] = Serial.read();
            //Serial.print(response[x]);
            x++;
            // check if the desired answer  is in the response of the module
            if (strstr(response, expected_answer) != NULL)
            {
                answer = 1;
            }
        }
    }
    // Waits for the asnwer with time out
    while((answer == 0) && ((millis() - previous) < timeout));

        return answer;
}

int8_t sendATcommand2(char* ATcommand, char* expected_answer1,
            char* expected_answer2, unsigned int timeout){

    uint8_t x=0,  answer=0;
    char response[100];
    unsigned long previous;

    memset(response, '', 100);    // Initialize the string

    delay(100);

    while( Serial.available() > 0) Serial.read();    // Clean the input buffer

    Serial.println(ATcommand);    // Send the AT command


        x = 0;
    previous = millis();

    // this loop waits for the answer
    do{
        // if there are data in the UART input buffer, reads it and checks for the asnwer
        if(Serial.available() != 0){
            response[x] = Serial.read();
            x++;
            // check if the desired answer 1 is in the response of the module
            if (strstr(response, expected_answer1) != NULL)
            {
                answer = 1;
            }
            // check if the desired answer 2 is in the response of the module
            if (strstr(response, expected_answer2) != NULL)
            {
                answer = 2;
            }
        }
        // Waits for the asnwer with time out
    }while((answer == 0) && ((millis() - previous) < timeout));

        return answer;
}


 

 

Soft-Uart Tx only using software delays only

I was working on a code for a module on my GSM gateway today , for which I had given 1 pin of micro-controller to use as software Tx. Software UARTs usually uses timers to make them robust, but I had already used them all. So I decided to write a code using software delays.

The UART logic is inverted , so to send logic 1 you have to send low signal  and vice versa . Here is my code , hope it might help someone else.

/*
* soft-uart Tx only without any timmer uses software delays
* the baud rate depends on the delay in us , here I am using
* 4800 with a 1 start bit, 8 databits and 1 stop bit
* if you wanna change the baud rate calculate it by 1/baud and
* modify the _delay_us();
*
* Created: 11/21/2012 1:52:37 PM
* Author: AbuUmar
*/
#include <avr/io.h>
#include <util/delay.h>
#define portlow PORTC&=~0x01
#define porthigh PORTC|=0x01
void putchar_soft(char data_soft)
{
 char bit_count=10; // 1+8+1SB
 data_soft=~data_soft;
 char secc=1;char0:
 if (secc=1)
 portlow;
 else
 porthigh;
 _delay_us(208);
 //_delay_us(208);
 for ( char i = 0; i < 8; i++ ) {
 if(data_soft & 1)
 portlow;
 else
 porthigh;
 data_soft=data_soft>>1;
 _delay_us(208);
 }
 porthigh;
 _delay_us(208);
 _delay_us(208);
 return;
}
int main(void)
{
 DDRC|=0b00000001;
 porthigh;
char inte=0;
while(1)
 {
 // example use, initializing a var to 0 and sending the data
 // with 1 sec delays
 putchar_soft(inte) ;
 _delay_ms(250);
 _delay_ms(250);
 _delay_ms(250);
 _delay_ms(250);
 inte++;
 }
}
 

STM32 Microcontrollers – Prior to Start

STM32 ARM-based micros from STMicroelectronics pack high density resources than any other conventional microcontroller. They are also high speed devices, operating typically at 72MHz and beyond. Despite several advanced features and heavy resources, they turn out to be misfortunes for beginners who wish to play with them. Available in market are several cool STM32 boards but most of them are not well documented. The aim of this document is to address some common FAQs.

Typically most people ask the following question:

  • How to program the STM32 micro embedded in my development board?
  • What tools do I need to get started?
  • What compiler support do I have for STM32?
  • What resources are available for STM32 on the internet?

… 

 

yet another seven segment display code generator/calculator

Yesterday I made a post regarding a seven segment display code generator, One of our reader Zafer shared his work with us through the comments section. Its a nice and useful utility. Its in Turkish language but its easy to use. Download it here  from Dropbox.

Hi Muhammad
I follow your site with interest.
I’ve prepared the following program. hopefully be useful.
Zafer
http://yadi.sk/d/0PqFkSf2P9gJr

 

 

Seven segment Display code generator / calculator

I found this awesome code generator for seven segments. There are many out there but this one has some good features. first of all you can decide which Segment is attached to which pin  [all pins should be on one port].  secondly you can get values for multiple characters and the code generator will make an array of values for you .

Give it a try. It can be downloaded here  or from codeplex website.

Capture

 

“COM Port Physical Interface Model” COMPIM from PROTEUS

I found an interesting feature from Proteus, so-called COMPIM serial port model. The Virtual System Modeling capabilities of Proteus VSM allow the creation of models that can actually interact with the physical world. Such models are called Physical Interface Models or PIMs for short.

The COMPIM model is a Physical Interface Model of a serial port. Incoming serial data is buffered and presented to the circuit as a digital signal, whilst serial digital data generated by a CPU or UART model appears at the PC’s physical COM port. The physical COM part also includes virtual COM port over USB and Bluetooth with some work-around. The COMPIM model also provides for baud rate translation, and for optional hardware or software handshaking on both the physical and virtual sides of the device.

This allows any real world hardware equipped with a serial port to interact with a Proteus VSM simulation. For example, you could use it to develop a program for a microprocessor within Proteus VSM that would operate a real physical modem, perhaps as part of a security or home automation system. By default, the COMPIM supports 4 physical ports.

 

writing and reading from AVR EEPROM in Block.

EEPROM can be used to store non volatile data of the program , sometimes you need to write arrays even multidimensional. The way I do it is by using EEMEM attribute. EMMEM is used to allocate space in EEPROM.

I use the Macros given below to write or read to EEPROM. you have to use #include I would be precise . below is the Code.

#include

//////////////////////////////////////////////////////////////////////////
//        Macros and # Defines
//write block to EEPROM
#define eepw(message,EEADDR,BLKSIZE) eeprom_write_block((const void*)message,(void*)EEADDR,BLKSIZE);
//read block from EEPROM
#define eepr(readblck,EEADDR,BLKSIZE) eeprom_read_block((void*)readblck,(const void*)EEADDR,BLKSIZE);

uint8_t EEMEM eepstring[15];

Example use

eepw("sample test 1",eestring, 15);  // "writes sample test1" to eestring in EEprom ,
char d[15];   //array in ram
eeprom_read(d, eestring[0],15); // reads the data and puts it in d[]

 

Keeping track of time in embedded applications: millis();

Its very handy to keep track of time in embedded programs. In this post I will implement a function called millis() which can be used to track time.  Arduino users will be familiar with this one. I would be doing it for AVR MCUs you can easily port it for others. this function returns the number of milliseconds since the MCU began running the current program. This number will overflow (go back to zero), after approximately 50 days.
It uses a hardware timer , in this post i will use timer0 . The first step is to initialize timer0 and interupts. lets start.

void timer0(){
  // To set clock:
  // 1MHZ is 1,000,000 ticks per second
  // 1000 milli in 1 second
  // xMHZ = 1000millis
  // so MHZ/millis gives # HZ per millis
  // (HZ/millis)/prescaler= Top counter number

  // EG:for 8MHZ clock
  // 8000000/1000
  // 8000.0000000000
  // 8000/256
  // 31.2500000000 TOP counter

  //set CTC (clear timer on compare match mode)
  TCCR0A = (1< <WGM01);
  //sets prescaler clkIO/256  ***THIS MIGHT CAUSE ISSUES SETS FOR ALL CLOCKS**!!!!
  TCCR0B = (1<<CS02);
  //sets interrupt enable for OCF0A (TIMER_COMPA_vect)
  TIMSK0 = (1<<OCIE0A);
  //sets TOP counter match A at 31
  OCR0A = 31;
}


volatile uint32_t millis()
{
 uint32_t mill;
 uint8_t oldSREG = SREG;
 // remember last value of interrupts
 // disable interrupts while we read timer0_millis or we might get an
 // inconsistent value (e.g. in the middle of a write to timer0_millis)
 cli();
 mill = millis_count;
 SREG = oldSREG; // rewrite reg value to turn back on interrupts
 return mill;
}

In the code shown above we have initialized timer/counter 0 to make an interrupt after every millisecond. Next we have to update our millisecond count.

//interrupt declaration
ISR(TIMER0_COMPA_vect)
{
  ++millis_count;
  //OCR0A = 10; //sets upper breakpoint A
}

That’s it. Lets see how to use it! First we copy the current value in milis() to a variable.

uint32_t starttime=millis();

and later we compare the new values with the start value. Here’s an example of a 25 second.

if(millis()-starttime > 25000)
{
  // some code here
}

Note that the parameter for millis() is an unsigned long, errors may be generated if a programmer tries to do math with other datatypes such as ints.

There are a number of ways you can use this. Hope this post will help you

 

Disable CLK Pre-scaler in AVR to use 8MHz Internal Oscilator

Just wanted to share this small piece of information that can help many . If you want to Run your AVR at 8MHz from the internal oscillator you need to disable the CLK/8 Fuse. You can do this by burning new fuse values. This can also be done in you main function as well. Below is a piece of code that will change the pre-scaler to zero.

// set the clock speed to "no pre-scaler" (8MHz with internal osc or
// full external speed)
// set the clock prescaler. First write CLKPCE to enable setting of clock the
// next four instructions.
CLKPR=(1< 

Hope this will help!

 

Add Voice /Audio to projects using WTV020SD

Adding sound to your projects is great, there can be several methods to do it. In this post i will show how we can use wtv020-sd module to get this task done. I wont go in detailed description of the module and will keep the post short and to the point. The module can be operated in a number of modes including pushbutton modes but the one we are going for is the 3 wire serial mode. its actually SDA,SCL and reset wires that we use. The module would play back the ad4 files stored on uSD Card. and spk+ and spk- pins can be connected directly to a speaker. More details about the module can be found in the datasheet and the webpage link.

The interface is simple. you only need to connect Supply , DI ,CLK and reset Pins to get it working although you may also connect some other pins also but this is what is really needed to get the module working.

connections …