Porter solare autonomo

Ciao a tutti ragazzi.
Sto realizzando un "porter" autonomo 24 ore su 24.
Il senso di tutto questo è un piccolo robot studiato per curare una pianta e gestirla anche per periodi relativamente lunghi. Grazie a due pannelli solari, uno adibito alla ricarica delle batterie ni-cad dei servi e l'altro per le batterie di arduino. sono due pannelli da 6.8v 180ma.
Visto che dovrà seguire il sole oppure spostarsi e cercare una zona piu' fresca, non avrà bisogno di muoversi velocemente (penso che 3 o 4 cm al secondo bastino). Volevo aggiungere un minimo di interattività con noi umani applicando le semplici casse piezo, una input per poter sentire battiti di mani o urla (mi spiegate come renderle piu' sensibili??) e una output per emettere suoni casuali in determinate situazioni. Ah dimenticavo un inmancabile led verde.
Ho bisogno di ottimizzare il piu' possibile l'utilizzo delle porte perchè scarseggiano.

Allora collegherò
-inmancabile led verde
-cicalino piezo input
-cicalino piezo out
-2 servi
-due baffi per ostacoli

  • sensore di temperatura
    -sensore tilt sharp (qui ho un sacco di domande)
    -un ultimo motore dc (pompa idraulica per l'acqua della pianta)

Vi piace l'idea? ;D ;D ;D
Ho delle grosse lacune di elettrotecnica e C per farlo senza chiedere un paio di consigli.
Per esempio, arduino puo' sentire quanti volt escono dai pannelli?Perchè se si basterebbe quello come sensore di luce.
Come si collega il sensore tilt sharp?

Se quello e'il tuo lavoro, vorrei averle io le grosse lacune tue :slight_smile:

l'idea e' molto bella :slight_smile:
per quanto riguarda i pannelli, arduino cosi' com'e' non puo' leggere il voltaggio. Quindi puoi scegliere: o ti fai un sistema per leggere il voltaggio, oppure ti prendi qualche componente fotosensibile (tipo questo). Io personalmente andrei per la seconda scelta, credo sia piu' semplice (cosi' ad occhio).

Il tilt sensor dovrebbe essere semplice da collegare ma non ho il datasheet sottomano..

Grazie dei complimenti, la foto non è recentissima cmq.

Ciao ragazzi ho gia giocato con i led infrarossi utilizzati come sensori di luce. Il problema è che non so quanto possano essere precisi.
E soprattutto mi porterebbero via piu' di una porta.
Ma se uso una porta analogica x collegare il pannello e dimezzo il voltaggio con una resistenza (quanti ohm di resistenza???) potrei sentire quanti volt escono dal pannello utilizzando una porta sola (a parte il ground che non conta).
No?

Uhm cosi' ad occhio direi che per una caduta di tre volt abbondanti mi sa che non ti basta una resistenza..
Poi non so se sia una buona idea usare il pannello sia per l'alimentazione sia come input.. ma non sono abbastanza esperto da dare un giudizio, magari si puo' fare.

Comunque anche con un LDR tipo la fotocellula che ti avevo linkato usi un solo pin analogico.

ehmmmm :-X
hai ragione.
faccio prima si indubbiamente.
Posto qui sotto il codice del primo walker che ho prodotto insieme a Martino e Vanni:

#include <Servo.h>

// words for clarity
#define LEFT 1
#define RIGHT 2
#define LEDBICOLOR 0
#define LEDTRICOLOR 1

// parameters
#define BUMPS_TO_STOP 5                 // number of obstacles to stop after
#define RANDOM_START_SECONDS 120        // mean time in seconds for random start
#define RANDOM_SOUND_SECONDS 30         // mean time in seconds for random sound
#define RANDOM_STEER_SECONDS 3          // mean time in seconds for random steering
#define BACKWARD_MSECONDS 800           // time to go back after hitting an obstacle in milliseconds
#define ROTATION_MSECONDS 500           // duration of the rotation in milliseconds
#define STEER_MSECONDS 1000             // duration of the random steering
#define SPEED 100                       // speed to go
#define STEER_PERCENT 3                 // percent of SPEED to set one of the servos to steer
#define SNDMEAN 150                     // number of samples to mean

// digital pins
#define ledPin1      2                  // LED 0 red
#define ledPin2      3                  // LED 0 green
#define ledPin3      4                  // LED 1 blue
#define ledPin4      5                  // LED 1 green
#define ledPin5      6                 // LED sensor
#define winkerPin1   7                  // winker LEFT
#define winkerPin2   8                  // winker RIGHT
#define servoPin1    9                  // servo LEFT
#define servoPin2   10                  // servo RIGHT
#define outSndPin   11                  // speaker
#define ledPin6     12                  // LED sensor

// analog pins
#define inSndPin     5                  // sound sensor

// variables
float actualSpeed = 0.0;                // percent of actual moving speed we are accelerating to
boolean moving = false;                 // stopped or moving
int speedLeft = 0;                      // speed we want on left servo
int speedRight = 0;                     // speed we want on right servo
Servo left;
Servo right;

int contact = 0;                        // did we hit? where?
int contactCount = 0;                   // number of hits since start
int contactStep = 0;                    // part of the hit manouver we are in
long contactTime = 0;                   // time of hitting
boolean steering = false;               // steering or going straight
boolean lightCheck = true;

long lightTime = 0;                     // time of last light check
long startTime = 0;                     // time of last random start
long steerTime = 0;                     // time of last random steering change
long soundTime = 0;                     // time of last random sound

int meanSnd[SNDMEAN];                   // past values of sound sensor
long meanSndCount = 0;                  // number of values stored


// setup
void setup() {
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
  pinMode(ledPin6, OUTPUT);
  pinMode(winkerPin1, INPUT);
  pinMode(winkerPin2, INPUT);
  left.attach(servoPin1);
  right.attach(servoPin2);
  pinMode(outSndPin, OUTPUT);
  
  randomSeed(analogRead(0));
  digitalWrite(ledPin6, LOW);
  Serial.begin(9600);
}


// winkers
int checkContact() {
  if(digitalRead(winkerPin1) == LOW)
    return LEFT;
  if(digitalRead(winkerPin2) == LOW)
    return RIGHT;

  return 0;
}


// servo
void servoContinue() {
  if(moving) {
    if((actualSpeed < 1)) {
      actualSpeed += 0.009;
    }
    if(steering && (steerTime < millis() - STEER_MSECONDS)) {
      speedLeft = speedRight = max(speedLeft, speedRight);
      steering = false;
      steerTime = millis();
    }
  }
  
  servoSpeed(LEFT, round(speedLeft * actualSpeed));
  servoSpeed(RIGHT, round(speedRight * actualSpeed));
}

void servoGo(int speed) {
  if(speed < 0) {
    setLed(LEDBICOLOR, 1);
  }
  else {
    setLed(LEDBICOLOR, 0);
  }
  
  speedLeft = speedRight = speed;
  servoReset();
}

void servoReset() {
  actualSpeed = 0;
  servoContinue();
}

void servoRotate(int side) {
  setLed(LEDBICOLOR, 2);
  
  switch(side) {
  case LEFT:
    speedLeft = 40;
    speedRight = -40;
    break;
  case RIGHT:
    speedLeft = -40;
    speedRight = 40;
    break;
  }
  servoReset();
}

void servoSpeed(int side, int speed) {
  speed = speed * 90 / 100;
  switch(side) {
  case LEFT:
    left.write(90 + speed);
    break;
  case RIGHT:
    right.write(90 - speed);
    break;
  }
}

void servoSteer(int side) {
  steering = true;
  steerTime = millis();
  
  switch(side) {
  case LEFT:
    speedLeft = round(speedLeft * STEER_PERCENT / 100.0);
    break;
  case RIGHT:
    speedRight = round(speedRight * STEER_PERCENT / 100.0);
    break;
  }
}


// LED
void setLed(int led, int state) {
  switch(led) {
  case LEDBICOLOR:
    switch(state) {
    case 0:
      digitalWrite(ledPin1, LOW);
      digitalWrite(ledPin2, LOW);
      break;
    case 1:
      digitalWrite(ledPin1, HIGH);
      digitalWrite(ledPin2, LOW);
      break;
    case 2:
      digitalWrite(ledPin1, LOW);
      digitalWrite(ledPin2, HIGH);
      break;
    }
    break;
  case LEDTRICOLOR:
    switch(state) {
    case 0:
      digitalWrite(ledPin3, LOW);
      digitalWrite(ledPin4, LOW);
      break;
    case 1:
      digitalWrite(ledPin3, LOW);
      digitalWrite(ledPin4, HIGH);
      break;
    case 2:
      digitalWrite(ledPin3, HIGH);
      digitalWrite(ledPin4, HIGH);
      break;
    }
  }
}


// sound
void sndPlay(int sound) {
  switch(sound) {
  case 0:               // sound when hitting an obstacle
    sndTone(1275);
    sndTone(1915);
    sndTone(2000);
    break;
  case 1:               // sound when starting
    sndTone(2100);
    sndTone(1500);
    sndTone(1200);
    break;
  case 2:               // random sound
    for(int i = 0; i < 3; i++)
      sndTone(random(1200, 3000));
    break;
  }
}

void sndTone(int tone) {
  for(long i = 0; i < 80000; i += tone * 2) {
    digitalWrite(outSndPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(outSndPin, LOW);
    delayMicroseconds(tone);
  }
}


// movement
void start() {
  contactCount = 0;
  steerTime = soundTime = millis();
  moving = true;
  servoGo(SPEED);
  sndPlay(1);
  setLed(LEDTRICOLOR, 2);
}

void stop() {
  startTime = millis();
  meanSndCount = 0;
  moving = false;
  servoGo(0);
  setLed(LEDTRICOLOR, 0);
}

void hit() {
  contactCount++;
  servoGo(-SPEED);
  sndPlay(0);
}


// time
long randomTime(long since, long about) {
  return since - (millis() - round(about * random(5, 15) / 10));
}


// main loop
void loop() {
  if(! moving) {
    if(lightTime < millis() - 1000) {
      lightTime = millis();
      long light = 0;
      for(int i = 0; i < 3; i++) {
        pinMode(ledPin5, OUTPUT);
        digitalWrite(ledPin5, HIGH);
        pinMode(ledPin5, INPUT);
        digitalWrite(ledPin5, LOW);
        for(; light < 90000; light++)
          if(digitalRead(ledPin5) == 0)
            break;
      }
      lightCheck = light < 10000;
      
      Serial.println(light);
      if(lightCheck)
        setLed(LEDBICOLOR, 2);
      else
        setLed(LEDBICOLOR, 1);
    }
    
    if(lightCheck && randomTime(startTime, RANDOM_START_SECONDS * 1000L) < 0)
      start();
  }
  else if(contactStep == 0) {
    if(randomTime(soundTime, RANDOM_SOUND_SECONDS * 1000L) < 0) {
      soundTime = millis();
      sndPlay(2);
    }
    
    // check number of hits
    int remaining = BUMPS_TO_STOP - contactCount;
    if(remaining == 0)
      stop();                     // too many hits, stop ;)
    else if(remaining == 1)
      setLed(LEDTRICOLOR, 1);     // turn off one led, we are going to stop next hit
  }
  
  if(! moving) {
    // sound sensor to start
    int snd = analogRead(inSndPin);
    meanSnd[meanSndCount++ % SNDMEAN] = snd;
    if(meanSndCount >= SNDMEAN) {
      float mean = 0;
      for(int i = 0; i < SNDMEAN; i++)
        mean += meanSnd[i];
      mean /= SNDMEAN;
    
      if(lightCheck && (snd < round(mean) - 1))
        start();                  // sound activated start
    }
  }
  else {
    // moving and hitting obstacles
    switch(contactStep) {
    case 0:                       // moving straight
      contact = checkContact();
      if(contact != 0) {
        contactStep = 1;
        contactTime = millis();
        hit();
      }
      else {
        if((! steering) && (randomTime(steerTime, RANDOM_STEER_SECONDS * 1000L) < 0))
          servoSteer(random(LEFT, RIGHT + 1));
      }
      break;
    case 1:                       // moving backwards after hit
      if(contactTime < millis() - BACKWARD_MSECONDS) {
        contactStep = 2;
        servoRotate(contact);
      }
      break;
    case 2:                       // rotating after moving backwards
      if(contactTime < millis() - (BACKWARD_MSECONDS + ROTATION_MSECONDS + random(0, 200))) {
        steerTime = millis();
        contactStep = 0;
        servoGo(SPEED);
      }
    }
  }
  
  // go on accelerating
  servoContinue();
}

Ringrazio di nuovo Martino DiFilippo per il C e l'ingegneria software.

Il codice originale non è esattamente quello che ho bisogno:
Il porter dovrà controllare la temperatura ogni secondo, if la temp (temperatura istantanea acquisita) è < goodtemp (la temperatura adatta alla vita della pianta) il robot dovrà entrare in void start e ricercare una zona dove temp=goodtemp, se invece temp è > di goodtemp il robot dovrà entrare in void start e ricercare un'altra zona dove temp=goodtemp. Dovrà controllare ogni quarto di secondo quanta luce acquisisce dal sensore di luce, se la light (luce istantanea acquisita) < di goodlight (luce adatta alla vita della pianta e delle batterie :wink: ), il robot dovrà entrare in void start e ricercare una zona dove light=goodlight , in questo caso se light > di goodlight ricontrolli se temp>goodtemp in quel caso void start.

queste piu' o meno dovrebbero essere le sue funzionalità che di base vorrei implementare al codice originale.
Non so se utilizzare un sensore di umidità per l'irrigazione oppure semplicemente impostare un timer per un innaffiamento ciclico.

ciao ragazzi.
Sto trasferendo lo schema elettrico su questa proto shield:
http://www.robot-italy.com/product_info.php?cPath=1_119&products_id=879
Non riesco a trovare che resistenze devo montare tra interruttore e icsp e soprattutto non ho capito che cos'è l' IC1. La scheda è predisposta per alloggiare questo componente.