Aprenda a Programar o Arduino parte 4

Estamos aqui mais uma vez para falar sobre o Arduino, o tutorial dessa vez será um pouco mais curto, pois estou trabalhando em meu projeto de iniciação científica, além de precisar estudar física e OpenGL de preferência hoje ainda. Mas nem por isso vamos deixar de tirar proveito deste post ok?

Para quem está acompanhando estas postagens a medida que elas estao sendo lançadas Houveram 2 alterações, houve uma errata postado na Parte 2, e como havia comentado no forum do Arduíno estava estudando a possibilidade de inserir algumas sugestões do Bubulindo.

Então let’s go!

Estrutura de Pastas do Arduíno

Estrutura de pastas do Arduino
Estrutura de pastas do Arduino

Quando acessamos a pasta do Arduino vemos uma estrutura como mostrada na imagem acima, não há muito o que falar sobre a organização, mas destacam-se as pastas que marquei em vermelho.

– examples – Contém os sketchs de exemplos os mesmos que você acessa no menu file->examples

– reference – Contem arqivos html de ajuda, os mesmo que existem no site do Arduino e que voce pode acessar no menu help->reference

e os dois mais importantes

– libraries – contem as bibliotecas do sistema chegamos inclusive a criar uma na Parte 3 desse tutorial voce pode inserir uma librarie usando a diretiva #include ou acessando o menu sketch->import Libray

– hardware – essa pasta contem a implementação da linguagem c/c++ usada no arduíno e é sobre ela que iremos falar hoje.

 

O Header Arduino.h

O Header Arduino.h se encontra  na pasta hardware\arduino\cores\arduino ele e responsavel pela definição dos protótipos de classes e por incluir todo o core do arduino portanto quando incluimos o Arduino.h na library que criamos o que estamos fazendo e importar todo o core do Arduino e assim podemos utilizar os comandos implementados nessa linguagem. Nesse arquivo você pode ver os seguintes includes:

#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include “binary.h”
#include “pins_arduino.h”

#include “WCharacter.h”
#include “WString.h”
#include “HardwareSerial.h”

Bom então já sabemos quais as bibliotecas que estão disponiveis no core, ou seja sem necessitarem de uma diretiva #include. Na prática o que isso nos fala é o seguinte:

Programa em linguagem C utilizado em um PC.

#include <math.h>

main(){

float a = cos(30);

}

Ja no Arduíno

void setup(){}

void loop(){
float a = cos(30);
}

Ou seja apenas elimina a necessidade de incluirmos a biblioteca math.h, o mesmo ocorre para todas as outras que mostramos acima.

Outra coisa interessante no Arduino.h são as constantes predefinidas

#define HIGH 0x1
#define LOW  0x0

#define INPUT 0x0
#define OUTPUT 0x1

#define true 0x1
#define false 0x0

#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105

Na pratica isso nos diz que:

void setup(){
pinMode(13,1);
}

void loop(){}

é igual a:

void setup(){
pinMode(13,OUTPUT);
}
void loop(){}

 

Isso é interessante de saber pois  na maioria das bibliotecas são utilizados conceitos semelhantes a esse.

Outro local para ser observado nesse arquivo são as definições dos prototipos das funções:

void init(void);

void pinMode(uint8_t, uint8_t);
void digitalWrite(uint8_t, uint8_t);
int digitalRead(uint8_t);
int analogRead(uint8_t);
void analogReference(uint8_t mode);
void analogWrite(uint8_t, int);

unsigned long millis(void);
unsigned long micros(void);
void delay(unsigned long);
void delayMicroseconds(unsigned int us);
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);

void attachInterrupt(uint8_t, void (*)(void), int mode);
void detachInterrupt(uint8_t);

void setup(void);
void loop(void);

 

Aqui estão declaradas os prototipos dos comandos que utilizamos, lembrando que os comandos de C/C++ como os do Arduino, são na verdade funções e ou metodos!

Agora vamos parar um pouquinho e analizar o arquivo main.cpp

#include <Arduino.h>

int main(void)
{
init();

#if defined(USBCON)
USB.attach();
#endif

setup();

for (;;) {
loop();
if (serialEventRun) serialEventRun();
}

return 0;
}

Aqui podemos ver que foi inserido o Header do Arduino, depois o programa declara a função main, o void dentro do parentesis informa que essa função nao recebe parametro. Logo nao inicio da main, a função init(), é invocada, o que ela faz? Ela se encontra em Wiring.c você vê o código dela aqui ou então na pasta hardware\arduino\cores\arduino . Ela e um framework para microcontroladores AVR, e ela tem de ser executada antes de setup(), senão algumas funcionalidades deixam de funcionar.

Depois do tratamento da USB é iniciado a função setup(), essa função somente e prototipada em Arduino.h, que vai cria-la é você, no seu sketch, e o mesmo ocorre com a função loop, que se você verificar esta em um laço infinito. O comando if (serialEventRun) serialEventRun(); Entrou no loop para corrigir um problema que fazia com que o hwserial, não fose acionado a cada chamada ao loop como você pode ver no mail-list.

Por isso que na discussão o Bubulindo apontou meu erro, eu desviava a função setup para outra função que quando finalizava retornava ao setup() que ao finalizar passava para o loop infinito. Aproveitando que estamos aqui vamos implementar uma função end() que permita finalizar o programa do arduino, bom a utilidade disso é bem pouca, precisei disso num caso muito especifico mas bastava executar o loop vazio como mostrei na segunda parte desse tutorial. Mas vale a experiência.

Primeiro vamos criar o prototipo da função no Arduino.h. Coloquei o prototipo abaixo do prototipo de Setup() e loop()

void setup(void);
void loop(void);

void end (void);

Depois criamos algumas alterações no arquivo main.cpp

#include <Arduino.h>

unsigned short int continua = 1;
int main(void)
{
init();

#if defined(USBCON)
USB.attach();
#endif

setup();

while (continua > 0){
loop();
if (serialEventRun) serialEventRun();

}

return 0;
}

void end(void){

delay(100);

continua = 0;

}

 

Com essas pequenas alterações implementamos uma função que finaliza o programa, seu uso e super simples veja o codigo abaixo já utilizando essa função.

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

}

void loop(){

Serial.print(“Oi implementamos a função end \n”);

end();

}

 

Pronto se compilou corretamente sua IDE ja possui a função end!

Bom galera hoje vou parando por aqui, minha idéia e continuar na proxima parte falando sobre a biblioteca para cartões de memória, como ela funciona, como montar um “shield” ,não tem nem como dar esse nome, para cartão de memória. Espero sua visita!

att,

Anthony Collucci

9 ideias sobre “Aprenda a Programar o Arduino parte 4”

  1. Legal a dica de criar uma função “end()” para finalizar o programa. Mas acho que alterar o código das bibliotecas do core da IDE não é muito prático, pois elas são compartilhadas por todos os sketchs(projetos).

    Um solução menos intrusiva seria definir uma variável global em nosso sketch e adicionar um um “if” ou “while”(dependendo da necessidade) na nossa função loop().

    Exemplo:

    boolean _run = true;

    void setup() {}

    void loop() {
    while (_run) {
    run();
    }

    shutdown();
    }

    void run() {
    /* instruções principais */
    }

    void shutdown() {
    /* instruções antes de encerrar */
    }

    void end() {
    _run = false;
    }

    void start() {
    _run = true;
    }

    Apesar de que isso só é necessário num caso muito especifico mesmo! Acho que o que precisamos sempre é aguardar pela ação do usuário(como um apertar de botão) para continuar ou recomeçar a execução..

    Abraços!

    1. Erle,

      Obrigado pelo comentário,

      Mas no caso a função que você implementou, não para a aplicação, ela na verdade continua fazendo um loop infinito. A idéia era impedir que esse loop ocorre-se.

      No caso poderia ter sido utilizado tbm o exit(0), porem a saida abrupta do programa para qualquer coisa que esteja sendo feita imediatamente.

      Mas a idéia e essa mesmo somente executar algo quando necessario.

      Ps.: Muito legal o seu site.

      att,

  2. Estou desenvolvendo um webserver para monitorar o estado de um ldr, porém gostaria que a atualização da página se desse automaticamente a cada 5 minutos, porém não estou conseguindo, tens alguma dica?

    1. Gabriel,

      Bom dia,

      Em qual linguagem você esta desenvolvendo seu “webserver” me passe mais detalhes.

      Se for o que eu imaginei, você esta desenvolvendo uma pagina web que se conecta ao arduíno, se for assim bastaria um refresh a cada 5 minutos. Mas aguardo suas informações para entender melhor.

      abç

  3. Olá,
    Estou com uma dúvida, se alguém puder me ajudar, ficarei muito agradecido.
    Tenho um código só para inicialização do shield gsm, ele tá funcionando perfeitamente. Segue o código:
    int powerkey = 5;
    int statuspin = 6;
    int pinState = 0;
    String inputString = “”; // a string to hold incoming data
    boolean stringComplete = false; // whether the string is complete

    void setup() {
    // initialize serial:
    Serial.begin(9600);
    pinMode(powerkey, OUTPUT);
    pinMode(statuspin, INPUT);
    inputString.reserve(200);
    }

    void loop()
    {
    pinState = digitalRead(statuspin);
    if(pinState==LOW){
    digitalWrite(powerkey, HIGH); // set the LED on
    delay(2000);
    digitalWrite(powerkey, LOW);
    }
    }
    Porém, qdo eu implemento as outras funções que eu preciso ele para de funcionar. Segue o código completo:
    // include the GSM library
    #include

    // PIN Number for the SIM
    #define PINNUMBER “”

    // initialize the library instances
    GSM gsmAccess;
    GSM_SMS sms;

    // Array to hold the number a SMS is retreived from
    char senderNumber[20];
    int led1 = 13;
    int powerkey = 5;
    int statuspin = 6;
    int pinState = 0;
    String inputString = “”; // a string to hold incoming data
    boolean stringComplete = false; // whether the string is complete

    void setup()
    { Serial.begin(9600);
    pinMode(led1, OUTPUT);
    digitalWrite(led1, LOW);
    // initialize serial communications and wait for port to open:

    pinMode(powerkey, OUTPUT);
    pinMode(statuspin, INPUT);
    inputString.reserve(200);
    while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
    }

    Serial.println(“Serial iniciada”);

    // connection state
    boolean notConnected = true;

    // Start GSM connection
    while(notConnected)
    {
    if(gsmAccess.begin(PINNUMBER)==GSM_READY)
    notConnected = false;
    else
    {
    Serial.println(“Não conectado”);
    delay(100);
    }
    }

    Serial.println(“GSM inicializado”);
    Serial.println(“Aguardando mensagens”);
    }

    void loop()
    {
    pinState = digitalRead(statuspin);
    if(pinState==LOW){
    digitalWrite(powerkey, HIGH); // set the LED on
    delay(2000);
    digitalWrite(powerkey, LOW);
    }
    }
    /* instruções principais */

    void run()
    {

    char c;

    // If there are any SMSs available()
    if (sms.available())
    {
    Serial.println(“Mensagem recebida de:”);

    // Get remote number
    sms.remoteNumber(senderNumber, 20);
    Serial.println(senderNumber);

    // An example of message disposal
    // Any messages starting with # should be discarded
    if(sms.peek()==’#’)
    {
    digitalWrite(led1, HIGH);
    Serial.println(“O Portao esta sendo aberto”);
    }
    if(led1,HIGH)
    {
    Serial.println(“Portao aberto”);
    sms.beginSMS(senderNumber);
    sms.print(“portao aberto”);
    sms.endSMS();
    sms.flush();
    }
    else if (sms.peek()==’*’)
    {
    digitalWrite(led1, LOW);
    Serial.println(“Portao fechado”);
    }

    // Read message bytes and print them
    while(c=sms.read())
    Serial.print(c);

    Serial.println(“\nFim da MENSAGEM”);

    // Delete message from modem memory
    sms.flush();
    Serial.println(“MENSAGEM APAGADA”);
    }
    delay(100);
    }

  4. primero quero agradecer por tamanha ajuda nao sabia nada de arduino mais agora comecei a saber alguma coisa, gracas a vc.

    estou montando um carrinho a onde uso dois motores.a onde uso uma ponte h para movimentalos, seia frente-ré-direita-esquerda, o problema e que não tenho o codico, mais como tou começando, teria como me enviar o codico, como exemplo para mim ir estudando o codico. sou grato,
    aguardo o seu retorno.

  5. olá, tenho uma dúvida entre as seguintes afirmações para meu trabalho:

    “O método setup() compreende o bloco de código onde são definidas as variáveis que serão utilizadas na programação e o método loop() compreende o bloco de código onde a execução do programa acontece de fato.”

    “O método loop() compreende um bloco de código que se executa infinitamente a menos que o arduino seja desligado ou que seja apertado o botão reset na placa ou que um novo programa seja carregado na plataforma, bem como o método setup() compreende o bloco de código responsável por criar o estado inicial de toda a execução do programa.”

    Afinal de contas, qual das duas afirmações é verdadeira?

    obrigado

    1. Bom as duas afirmações são verdadeiras, só que a segunda esta mais completa que a primeira, mas uma não contradiz a outra.

      O setup() e a preparação para execução, onde se defini estado inicial de algumas variáveis, defini-se pinos de entrada e saída.
      O metodo loop() e onde o programa executa continuamente.

      att,

  6. Estou fazendo um projeto para envio de String ao meu Servidor, já funciona mas esta muito instavel, poderia me ajudar? parece que no final após o envio ele reinicia, tirei o IP do meu servidor pois ele possui outras aplicações e não posso divuga-lo. segue o codigo.

    #include
    #include
    #define POWERPIN 4 //
    #define BUFFSIZ 90 //
    //Variaveis da Conexão GPRS
    SoftwareSerial cell(2, 3);
    char at_buffer[BUFFSIZ];
    char buffidx;
    String command = “”;
    int i = 1;
    int firstTimeInLoop = 1;
    int GPRS_registered;
    int GPRS_AT_ready;
    char incoming_char = 0;
    char buffer[60];
    String myString = “1”;
    String message;
    char sendStatus[30];
    boolean sent;
    int VerdePin=5;
    int AmareloPin=6;
    int VermelhoPin=7;

    boolean Connected;

    void cleanBuffer() {
    delay(500);
    while(cell.available() >0) cell.read();
    }

    void sendData(String data)
    {
    cell.print(“AT+SSTRSEND=1,\””);
    cell.print(data);
    cell.println(“\””);

    // delay(1000);
    // i=0;
    // while(true){
    //
    // for(int x = 0; x0)
    // {
    // incoming_char = cell.read();
    // Serial.print(incoming_char);
    // //if (incoming_char == ‘\n’ || incoming_char == 96) break;
    // sendStatus[i] += incoming_char;
    //// if(i>=(strlen(“OK”) +2)){
    //// break;
    //// }
    // i++;
    // }
    // }
    // if (strstr(sendStatus, “OK”) == 0)
    // {
    // Serial.println(sendStatus);
    // sent = true;
    // }
    // else{
    // Serial.println(sendStatus);
    // Serial.println(“Erro”);
    // sent = false;
    // }
    }

    void setup()
    {
    //Configuração do console
    Serial.begin(9600);
    //Configuração dos Leds
    pinMode(VerdePin, OUTPUT);
    pinMode(AmareloPin, OUTPUT);
    pinMode(VermelhoPin, OUTPUT);
    //Configuração do SM5100B
    cell.begin(9600);
    Serial.println(“Starting SM5100B Communication…”);
    delay(5000);
    GPRS_registered = 0;
    GPRS_AT_ready = 0;

    while (cell.available())
    {
    incoming_char = cell.read();
    Serial.print(incoming_char);
    }
    }

    void readATString(void) {
    char c;
    buffidx = 0; // start at begninning
    while (1) {
    if (cell.available() > 0) {
    c = cell.read();
    if (c == -1) {
    at_buffer[buffidx] = ”;
    return;
    }

    if (c == ‘\n’) {
    continue;

    }

    if ((buffidx == BUFFSIZ – 1) || (c == ‘\r’)){
    at_buffer[buffidx] = ”;
    return;
    }

    at_buffer[buffidx++] = c;
    }
    }
    }

    void ProcessATString() {
    if (strstr(at_buffer, “+SIND: 8”) != 0) {
    GPRS_registered = 0;
    Serial.println(“GPRS Network Not Available”);
    delay(10000);
    }

    if (strstr(at_buffer, “+SIND: 11”) != 0) {
    GPRS_registered = 1;
    Serial.println(“GPRS Registered”);
    delay(40000);
    }

    if (strstr(at_buffer, “+SIND: 4”) != 0) {
    GPRS_AT_ready = 1;
    Serial.println(“GPRS AT Ready”);
    delay(15000);
    }

    }

    void connectServer()
    {

    while (GPRS_registered == 0 && GPRS_AT_ready == 0) {
    readATString();
    ProcessATString();
    }

    while (cell.available()>0)
    {
    incoming_char = cell.read();
    Serial.print(incoming_char);
    }

    cleanBuffer();

    Serial.println(“Setting up PDP Context”);
    cell.println(“AT+CGDCONT=1,\”IP\”,\”Servidor\””);
    Serial.println(“AT+CGDCONT=1,\”IP\”,\”Servidor\””);
    delay(4000);
    while (cell.available()){
    incoming_char = cell.read();
    Serial.print(incoming_char);
    }

    cleanBuffer();

    Serial.println(“Sending Password”);
    delay(4000);
    while (cell.available()){
    incoming_char = cell.read();
    Serial.print(incoming_char);
    }

    cleanBuffer();

    Serial.println(“Activating PDP Context”);
    cell.println(“AT+CGACT=1,1”);
    Serial.println(“AT+CGACT=1,1”);
    delay(8000);
    while (cell.available()){
    incoming_char = cell.read();
    Serial.print(incoming_char);
    }

    cleanBuffer();

    Serial.println(“Configuring TCP connection to TCP Server”);
    cell.println(“AT+SDATACONF=1,\”TCP\”,\”Servidor\”,porta”);
    Serial.println(“AT+SDATACONF=1,\”TCP\”,\”Servidor\”,porta”);
    delay(4000);
    while (cell.available()){
    incoming_char = cell.read();
    Serial.print(incoming_char);
    }

    cleanBuffer();

    delay(4000);
    Serial.println(“Starting TCP Connection\n”);
    cell.println(“AT+SDATASTART=1,1”);
    Serial.println(“AT+SDATASTART=1,1”);
    delay(8000);
    while (cell.available())
    {
    incoming_char = cell.read();
    Serial.print(incoming_char);
    }

    }

    void VerifyConnection()
    {
    delay(500);
    cleanBuffer();
    Serial.println(“Checking Connection Status\n”);
    delay(1000);
    cell.println(“AT+SDATASTATUS=1”);
    Serial.println(“AT+SDATASTATUS=1″);
    delay(2000);
    char Status[35]=””;
    i=0;
    while (cell.available()>0)
    {
    incoming_char = cell.read();
    Serial.print(incoming_char);
    //if (incoming_char == ‘\n’ || incoming_char == 96) break;
    Status[i] += incoming_char;
    i++;
    delay(10);
    }

    cleanBuffer();
    const char ValidationChar[10] = ” 1,1,”;
    if(strstr(Status, ValidationChar)!=0) //if (strstr(Status, “1,1”))
    {
    Serial.println(“Connectado”);// Unica Saida!
    Connected = true;
    }
    else{
    Serial.println(“Nao Conectado”);
    Connected = false;

    }
    }

    void loop() {

    while (Serial.available()>0)
    {
    message = “”;
    while (Serial.available()>0)
    {
    delay(10);
    incoming_char = Serial.read();
    message += incoming_char;

    if (message.length()==16)
    {
    Serial.println(“Maior que 16”);
    message += ‘;’;
    }
    if (message.length()==33)
    {
    Serial.println(“Maior que 33”);
    message += ‘;’;
    }
    if (message.length()==50)
    {
    Serial.println(“Maior que 50”);
    message += ‘;’;
    }
    }
    Serial.print(message);
    sent = false;
    digitalWrite(VerdePin, HIGH);
    delay(10000);
    while(sent==false)
    {
    connectServer();
    VerifyConnection();

    if(Connected)
    {
    sendData(message);
    sent = true;
    }else{
    Serial.println(“Não Conectado ao Enviar”);
    sent = false;

    }
    }
    digitalWrite(VerdePin, LOW);
    }
    }

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Please type the characters of this captcha image in the input box

Por favor, digite os caracteres desta imagem na caixa de entrada