SOLUCIONADO - Arduino sube el sketch y luego no se reconoce en el PC

Buenas tardes, estoy realizando un proyecto que incluye BLEND MICRO y un sensor de ultrasonido hc-sr04 alimentado con un circuito casero y un Adafruit MCP73871.

La cuestion es que haciendo pruebas de consumo he subido un sketch de standby a la placa y funciona bastante bien, ahora he unido el sketch de standby con el de las medidas de ultrasonido y el resultado es que deja de reconocer el dispositivo y windows pasa a llamarlo Unknown device con driver genericos y todo, pero ya no se reconoce como puerto COM.

Si cargo un sketch de ejemplo (Blink) debo de hacerlo justo cuando pone cargando apretando el boton de reset a la vez y asi pasa a ser de nuevo un puerto COM pero sigo sin poder subir el sketch.

Sketch de standby y medida:

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

int PowerPin = 9;            // LED connected to digital pin 13
int sleepPin = 12;          // active LOW, ground this pin momentary to sleep
int wakePin = 2;            // active LOW, ground this pin momentary to wake up
int sleepStatus = 0;        // variable to store a request for sleep

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup(){
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.

  pinMode(PowerPin, OUTPUT);         // sets the digital pin as output
  pinMode(sleepPin, INPUT);        // sets the digital pin as input
  pinMode(wakePin, INPUT);

  /* Now is time to enable a interrupt. In the function call 
   * attachInterrupt(A, B, C)
   * A   can be either 0 or 1 for interrupts on pin 2 or 3.   
   * 
   * B   Name of a function you want to execute while in interrupt A.
   *
   * C   Trigger mode of the interrupt pin. can be:
   *             LOW        a low level trigger
   *             CHANGE     a change in level trigger
   *             RISING     a rising edge of a level trigger
   *             FALLING    a falling edge of a level trigger
   *
   * In all but the IDLE sleep modes only LOW can be used.
   */

  attachInterrupt(0, wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
                                      // wakeUpNow when pin 2 gets LOW 
}



void sleepNow()         // here we put the arduino to sleep
{
    /*
     *
     * In the avr/sleep.h file, the call names of these sleep modus are to be found:
     *
     * The 5 different modes are:
     *     SLEEP_MODE_IDLE         -the least power savings 
     *     SLEEP_MODE_ADC
     *     SLEEP_MODE_PWR_SAVE
     *     SLEEP_MODE_STANDBY
     *     SLEEP_MODE_PWR_DOWN     -the most power savings
     *
     * For now, we want as much power savings as possible, 
     * so we choose the according sleep modus: SLEEP_MODE_PWR_DOWN
     * 
     */  
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here

    sleep_enable();              // enables the sleep bit in the mcucr register
                                 // so sleep is possible. just a safety pin 

    /* Now is time to enable a interrupt. we do it here so an 
     * accidentally pushed interrupt button doesn't interrupt 
     * our running program. if you want to be able to run 
     * interrupt code besides the sleep function, place it in 
     * setup() for example.
     * 
     * In the function call attachInterrupt(A, B, C)
     * A   can be either 0 or 1 for interrupts on pin 2 or 3.   
     * 
     * B   Name of a function you want to execute at interrupt for A.
     *
     * C   Trigger mode of the interrupt pin. can be:
     *             LOW        a low level triggers
     *             CHANGE     a change in level triggers
     *             RISING     a rising edge of a level triggers
     *             FALLING    a falling edge of a level triggers
     *
     * In all but the IDLE sleep modes only LOW can be used.
     */

    attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
                                       // wakeUpNow when pin 2 gets LOW 

    sleep_mode();                // here the device is actually put to sleep!!
                                 // 

    sleep_disable();             // first thing after waking from sleep:
                                 // disable sleep...
    detachInterrupt(0);          // disables interrupt 0 on pin 2 so the 
                                 // wakeUpNow code will not be executed 
                                 // during normal running time.
    delay(1000);                 // wat 2 sec. so humans can notice the
                                 // interrupt. 
                                 // LED to show the interrupt is handled


}



void wakeUpNow()        // here the interrupt is handled after wakeup
{
  //execute code here after wake-up before returning to the loop() function
  // timers and code using timers (serial.print and more...) will not work here.
}




void loop()
{
  delay(500);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  
  digitalWrite(PowerPin, HIGH);            // sets the LED on
  delay(1000);                           // waits for a second
  digitalWrite(PowerPin, LOW);             // sets the LED off
  delay(1000);                           // waits for a second
  sleepStatus = digitalRead(sleepPin);   // read sleep pin here. only active 
                                         //when blink led is off.
  if (sleepStatus == LOW) {            // start to put the device in sleep
      sleepNow();                      // sleep function called here
      }
}

Gracias por adelantado.

¿Que modelo de arduino usas?

Uso el IDE 1.0.5-r2 porque la guía de blend estaba realizada para ese.

Yo pregunto por el modelo de placa. Uno, Micro, Nano, Mega, Leonardo, Esplora...

Ahh vale perdon cameloco, es un Blend Micro de RedBearLab.

Vale, te explico. El blend, usa un Atmel 32u4, igual que el Micro, el leonardo y el esplora. Estos arduinos, usan el mismo Atmel 32u4, para todo, incluida la comunicación USB. Esto significa que, una vez cargado el código, se resetea el chip, y con ello, también la comunicación USB.

Yo tengo un ordenador con Windows 7 profesional 64bits, el cual, cuando cargo un sketch en un Micro (con el mismo Atmel 32u4) después de la carga, deja de reconocerme el arduino. Si quiero volver a cargar otra cosa, o incluso ver la consola serie por usb, tengo que cerrar el IDE, desconectar el arduino y volverlo a conectar, y si lo hago muchas veces, incluso tengo que resetear windows.

En cambio, tengo una tablet Microsoft Surface, con windows 8.1 pro 64bits, y despues de cargar algo, se resetea, pero vuelve a reconocerme el arduino.

No sé muy bien por qué pasa eso en el pc con windows 7, pero es así…

Pero no es que haya que reconectarlo, es que cuando se resetea windows los reconoce como un dispositivo diferente incluso desconectando y conectando, si consigo cargar otro sketch ya vuelve a reconocerlo… no se que hacer.

Gracias por tu ayuda

Si, es tipico de los que llevan el Atmega 32u4. ¿Has probado reiniciando windows? por hacer la prueba, a ver si pasa lo mismo que yo te digo.

Si, y no da resultado, lo único que funciona es borrando el sketch.

Es realmente extraño. ¿Puedes poner el sketch que te da el error? Mi idea es probar a cargarlo en un Arduino Micro? Lleva el mismo chip, y probar a ver si se reproduce el mismo error.

Es el de arriba puesto en la primera consulta del post.

Lo acabo de probar en un Arduino Micro, y hace exactamente lo que explicas. Para poder subir el sketch del blink y que vuelva a funcionar normalmente y me reconozca el puerto serie, he dejado pulsado el botón de reset, y lo suelto cuando sale "Uploading..." en el IDE.

Creo que lo que pasa con ese sketch, es que el micro entra en modo "sleep" y por eso no lo reconoce el PC, ya que el micro está "durmiendo" y como el puerto serie se gestiona a través del mismo micro, no es capaz de reconocerlo.

Muchas gracias, pero, como hago para ver el tiempo que tarda en medir y volverse a dormir, porque si comienza con el micro en modo sleep y no lo reconoce no puedo calcular el tiempo de medidas para que sea el mínimo posible.

He hecho algunas pruebas, aunque sin mucho éxito, pero si que me he dado cuenta de una cosa. Usas la interrupción 0, con el pin2. Si miramos la documentación de las interrupciones en arduino:

http://arduino.cc/en/Reference/AttachInterrupt

Vemos que para el leonardo (Atmega 32u4) la interrupción 0, aplica al pin 3, y la interrupción 1 al pin 2, de forma que, o cambias de interrupción, o cambias de pin, porque si no, no concuerda.

He vuelto a escribir el sketch con alguna correcion y sigue sin funcionar…

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <NewPing.h>

#define TRIGGER_PIN  12
#define ECHO_PIN     11
#define MAX_DISTANCE 200

int PowerPin = 9; // when this pin is HIGH, sensor on; when LOW, sensor OFF.
int sleepPin = 2; // when this pin is LOW, ground this pin momentary to sleep.
int wakePin  = 3; // when this pin is LOW, ground this pin momenary to wakeUp.
int sleepStatus = 0; //variable to store a request for sleep.

NewPing sonar (TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); //NewPing setup of maximum distance.

void setup(){
  Serial.begin(9600); //baud to serial monitor.

  pinMode (PowerPin, OUTPUT);
  pinMode (sleepPin, INPUT);
  pinMode (wakePin, INPUT);

  attachInterrupt (0, wakeUpNow, LOW); // use interrupt 0 (pin 3) and run function wakeUpNow when pin 3 gets Low.
}
void sleepNow(){ //put the arduino to sleep.

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//sleep mode.

  sleep_enable();

  detachInterrupt(0);

}
void wakeUpNow(){
}

void loop(){

  delay(500);
  unsigned int uS= sonar.ping();
  Serial.print("Ping");
  Serial.print(uS / US_ROUNDTRIP_CM);
  Serial.print("cm");

  digitalWrite(PowerPin, HIGH);
  delay(1000);
  digitalWrite(PowerPin, LOW);
  delay (1000);

  sleepStatus = digitalRead(sleepPin);

  if (sleepStatus == LOW){
    sleepNow();
  }
}

Como lo ves?

Explícame un poco cómo tiene que funcionar la cosa, ya que poniendo los pins 2 y 3 como INPUT_PULLUP me funciona y veo las medidas en el puerto serie.

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <NewPing.h>

#define TRIGGER_PIN  12
#define ECHO_PIN     11
#define MAX_DISTANCE 200

int PowerPin = 9; // when this pin is HIGH, sensor on; when LOW, sensor OFF.
int sleepPin = 2; // when this pin is LOW, ground this pin momentary to sleep.
int wakePin  = 3; // when this pin is LOW, ground this pin momenary to wakeUp.
int sleepStatus = 0; //variable to store a request for sleep.

NewPing sonar (TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); //NewPing setup of maximum distance.

void setup(){
  Serial.begin(9600); //baud to serial monitor.

  pinMode (PowerPin, OUTPUT);
  pinMode (sleepPin, INPUT_PULLUP);
  pinMode (wakePin, INPUT_PULLUP);

  attachInterrupt (0, wakeUpNow, LOW); // use interrupt 0 (pin 3) and run function wakeUpNow when pin 3 gets Low.
}
void sleepNow(){ //put the arduino to sleep.

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//sleep mode.

  sleep_enable();

  detachInterrupt(0);

}
void wakeUpNow(){
}

void loop(){

  delay(500);
  unsigned int uS= sonar.ping();
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM);
  Serial.println(" cm");

  digitalWrite(PowerPin, HIGH);
  delay(1000);
  digitalWrite(PowerPin, LOW);
  delay (1000);

  sleepStatus = digitalRead(sleepPin);

  if (sleepStatus == LOW){
    sleepNow();
  }
}

Lo que empiezo a pensar que no es buena idea, usar un arduino con un Atmel 32u4, si tienes que hacer las lecturas por el puerto serial USB, y ponerlo en modo sleep, ya que esto, afecta a la detección del puerto serial USB.

Vale, acabo de hacer una prueba con un Uno y con un Micro. Con el Uno, usando este código:

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <NewPing.h>

#define TRIGGER_PIN  12
#define ECHO_PIN     11
#define MAX_DISTANCE 200

int PowerPin = 9; // when this pin is HIGH, sensor on; when LOW, sensor OFF.
int sleepPin = 3; // when this pin is LOW, ground this pin momentary to sleep.
int wakePin  = 2; // when this pin is LOW, ground this pin momenary to wakeUp.
int sleepStatus = 0; //variable to store a request for sleep.

NewPing sonar (TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); //NewPing setup of maximum distance.

void setup() {
  Serial.begin(9600); //baud to serial monitor.

  pinMode (PowerPin, OUTPUT);
  pinMode (sleepPin, INPUT_PULLUP);
  pinMode (wakePin, INPUT_PULLUP);

  attachInterrupt (0, wakeUpNow, LOW); // use interrupt 0 (pin 3) and run function wakeUpNow when pin 3 gets Low.
}
void sleepNow() { //put the arduino to sleep.

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//sleep mode.

  sleep_enable();
  attachInterrupt(0, wakeUpNow, LOW);
  sleep_mode();
  sleep_disable();
  detachInterrupt(0);

}
void wakeUpNow() {
}

void loop() {

  delay(500);
  unsigned int uS = sonar.ping();
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM);
  Serial.println(" cm");

  digitalWrite(PowerPin, HIGH);
  delay(1000);
  digitalWrite(PowerPin, LOW);
  delay (1000);

  sleepStatus = digitalRead(sleepPin);

  if (sleepStatus == LOW) {
    sleepNow();
  }
}

Y con el Micro este:

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <NewPing.h>

#define TRIGGER_PIN  12
#define ECHO_PIN     11
#define MAX_DISTANCE 200

int PowerPin = 9; // when this pin is HIGH, sensor on; when LOW, sensor OFF.
int sleepPin = 2; // when this pin is LOW, ground this pin momentary to sleep.
int wakePin  = 3; // when this pin is LOW, ground this pin momenary to wakeUp.
int sleepStatus = 0; //variable to store a request for sleep.

NewPing sonar (TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); //NewPing setup of maximum distance.

void setup() {
  Serial.begin(9600); //baud to serial monitor.

  pinMode (PowerPin, OUTPUT);
  pinMode (sleepPin, INPUT_PULLUP);
  pinMode (wakePin, INPUT_PULLUP);

  attachInterrupt (0, wakeUpNow, LOW); // use interrupt 0 (pin 3) and run function wakeUpNow when pin 3 gets Low.
}
void sleepNow() { //put the arduino to sleep.

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//sleep mode.

  sleep_enable();
  attachInterrupt(0, wakeUpNow, LOW);
  sleep_mode();
  sleep_disable();
  detachInterrupt(0);

}
void wakeUpNow() {
}

void loop() {

  delay(500);
  unsigned int uS = sonar.ping();
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM);
  Serial.println(" cm");

  digitalWrite(PowerPin, HIGH);
  delay(1000);
  digitalWrite(PowerPin, LOW);
  delay (1000);

  sleepStatus = digitalRead(sleepPin);

  if (sleepStatus == LOW) {
    sleepNow();
  }
}

Con el Uno, funciona perfecto. Si pones a masa el pin 3, se pone en modo “sleep” y una vez así, pones a masa el pin 2 y vuelve a ponerse en funcionamiento, mostrando de nuevo los valores por el puerto serie usb.

Con el micro, al poner a masa el pin 2, se pone en modo “sleep”, de forma que también se pierde el puerto serie en el PC. Al poner el pin 3 a masa, se puede ver que vuelve a funcionar, porque el led del pin 9, se ve encenderse y apagarse, pero ya no vuelve a recuperarse el puerto serial usb, lo que confirma que usar para esto un arduino con Atmel 32u4, no es buena idea, si necesitamos el puerto serie usb.

La alternativa para arduino con Atmel 32u4 es esta:

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <NewPing.h>

#define TRIGGER_PIN  12
#define ECHO_PIN     11
#define MAX_DISTANCE 200

int PowerPin = 9; // when this pin is HIGH, sensor on; when LOW, sensor OFF.
int sleepPin = 2; // when this pin is LOW, ground this pin momentary to sleep.
int wakePin  = 3; // when this pin is LOW, ground this pin momenary to wakeUp.
int sleepStatus = 0; //variable to store a request for sleep.

NewPing sonar (TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); //NewPing setup of maximum distance.

void setup() {
  Serial1.begin(9600); //baud to Serial1 monitor.

  pinMode (PowerPin, OUTPUT);
  pinMode (sleepPin, INPUT_PULLUP);
  pinMode (wakePin, INPUT_PULLUP);

  attachInterrupt (0, wakeUpNow, LOW); // use interrupt 0 (pin 3) and run function wakeUpNow when pin 3 gets Low.
}
void sleepNow() { //put the arduino to sleep.

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//sleep mode.

  sleep_enable();
  attachInterrupt(0, wakeUpNow, LOW);
  sleep_mode();
  sleep_disable();
  detachInterrupt(0);

}
void wakeUpNow() {
}

void loop() {

  delay(500);
  unsigned int uS = sonar.ping();
  Serial1.print("Ping: ");
  Serial1.print(uS / US_ROUNDTRIP_CM);
  Serial1.println(" cm");

  digitalWrite(PowerPin, HIGH);
  delay(1000);
  digitalWrite(PowerPin, LOW);
  delay (1000);

  sleepStatus = digitalRead(sleepPin);

  if (sleepStatus == LOW) {
    sleepNow();
  }
}

El problema es que hay que poner uno de estos:

Conectado a los pins 0 y 1, para que podamos ver las lecturas en el PC a través del “USB2Serial light”, de forma que no perdemos el puerto en el pc, al no usar el del Atmel 32u4.

Buenas

LA idea es tener un sensor que haga medidas y las envíe vía bluetooth a un teléfono móvil o pc. Pero antes de integrar el bluetooth debo de saber cuanto consume y el tiempo que tarda en despertarse sin el bluetooth activado.

Por eso, debo de subir el sketch real sin bbluetooth y ver si funciona, una vez eso medir los parametros e integrar bluetooth para comparar el consumo.

El último código que he subido para el micro, te tiene que funcionar, y el bluetooth, substituiría el “USB2Serial light”, de forma que no importa que se pierda el control del puerto serial USB, ya que no lo usarás.

El código a usar, sería este:

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <NewPing.h>

#define TRIGGER_PIN  12
#define ECHO_PIN     11
#define MAX_DISTANCE 200

int PowerPin = 9; // when this pin is HIGH, sensor on; when LOW, sensor OFF.
int sleepPin = 2; // when this pin is LOW, ground this pin momentary to sleep.
int wakePin  = 3; // when this pin is LOW, ground this pin momenary to wakeUp.
int sleepStatus = 0; //variable to store a request for sleep.

NewPing sonar (TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); //NewPing setup of maximum distance.

void setup() {
  Serial1.begin(9600); //baud to Serial1 monitor.

  pinMode (PowerPin, OUTPUT);
  pinMode (sleepPin, INPUT_PULLUP);
  pinMode (wakePin, INPUT_PULLUP);

  attachInterrupt (0, wakeUpNow, LOW); // use interrupt 0 (pin 3) and run function wakeUpNow when pin 3 gets Low.
}
void sleepNow() { //put the arduino to sleep.

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//sleep mode.

  sleep_enable();
  attachInterrupt(0, wakeUpNow, LOW);
  sleep_mode();
  sleep_disable();
  detachInterrupt(0);

}
void wakeUpNow() {
}

void loop() {

  delay(500);
  unsigned int uS = sonar.ping();
  Serial1.print("Ping: ");
  Serial1.print(uS / US_ROUNDTRIP_CM);
  Serial1.println(" cm");

  digitalWrite(PowerPin, HIGH);
  delay(1000);
  digitalWrite(PowerPin, LOW);
  delay (1000);

  sleepStatus = digitalRead(sleepPin);

  if (sleepStatus == LOW) {
    sleepNow();
  }
}

Ahora no funciona correctamente, se enciende y no se vuelve a dormir.... el osciloscopio muestra como se esta alimentando constantemente sin bajar de tensión....