Table of Contents

SD Card Buddy

Sergiu Moga 332CB

Introducere

SD Card Buddy este un proiect Arduino care are ca scop expunerea unui shell prin care un utilizator poate interactiona cu sistemul de fisiere de pe un SD Card. Ideea proiectului este de a avea ceva micut si la indemana cu care poti modifica continutul de pe un SD Card, ceea ce il poate face util in anumite cazuri.

Descriere generală

Folosind o placuta compatibila Arduino, prin comunicare SPI cu 2 sclavi (un display si un modul de SD Card) o sa expun printr-un display un shell interactiv cu care utilizatorul poate naviga/citi/scrie intr-un sistem de fisiere de pe SD Card. Pentru interactionare se va folosi o tastatura improvizata (15-16 butoane legate la acelasi pin prin rezistente diferite pentru a le putea distinge cu ajutorul analogRead).

Hardware Design

Componente:

Schematic:

Software Design

Software utilizat:

Biblioteci utilizate:

Structuri de date utilizate:

int second_half = 0;
// ranges = {{1000, 1050}, {950, 1000}, {850, 900}, {450, 550}, {50, 150}}
int kbd_button_index[] = {4, 4, -1, -1, 3, 3, -1, -1, 2, 1, 0};
char kbd_buttons[2][4][5] = { { {'A', 'B', 'C', 'D', 'E'},
                                {'F', 'G', 'H', 'I'},
                                {'J', 'K', 'L', 'M'},
                                {' ', '0', '\n'}  },
                                { {'N', 'O', 'P', 'Q', 'R'},
                                  {'S', 'T', 'U', 'V'},
                                  {'W', 'X', 'Y', 'Z'},
                                  {'/', '0', '\n'}  } };
char cmd[50];
char output[150];
int cmd_index, output_index;

Functii/Algoritmi:

Setup:

void setupServer()
{
  server.on("/", htmlIndex);
 
  server.begin();
}
 
void htmlIndex()
{
  int replyCode = 200;
 
  String contentType = "text/html";
 
  memcpy(markdown + sizeof(head) - 1, message, sizeof(message));
 
  server.send(replyCode, contentType, markdown);
}
 
void connectToWiFi()
{
  WiFi.mode(WIFI_STA);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED)
    delay(500);
}
 
void setup()
{
  mySerial.begin(4800);
 
  delay(1000);
 
  connectToWiFi();
 
  setupServer();
}
void setup() {
  mySerial.begin(4800);
 
  if (!SD.begin(10)) {
    while (1);
  }
}

Loop:

void htmlIndex()
{
  int replyCode = 200;
 
  String contentType = "text/html";
 
  memcpy(markdown + sizeof(head) - 1, message, sizeof(message));
 
  server.send(replyCode, contentType, markdown);
}
 
void loop()
{
  mySerial.readBytes(message, sizeof(message));
 
  server.handleClient();
}
void list(File dir, int level) {  
  int len;
  while (true) {
    File entry =  dir.openNextFile();
 
    if (!entry) {
      return;
    }
 
    for (uint8_t i = 0; i < level; i++) {
      output[output_index++] = '-';
      output[output_index++] = '-';
    }
 
    len = strlen(entry.name());
    memcpy(output + output_index, entry.name(), len);
    output_index += len;
 
    output[output_index++] = '<';
    output[output_index++] = 'b';
    output[output_index++] = 'r';
    output[output_index++] = '>';
 
    if (entry.isDirectory()) {
      output[output_index++] = '<';
      output[output_index++] = 'b';
      output[output_index++] = 'r';
      output[output_index++] = '>';
 
      list(entry, level + 1);
 
    }
 
    entry.close();
  }
}
 
void cmd_exec() {
  char *p = strtok(cmd, " ");
  File file, dir;
  int offset, bytes_count;
 
  if (p) {
    if (*p == 'L') {
      p = strtok(NULL, " ");
 
      dir = SD.open(p);
 
      list(dir, 0);
 
      output[output_index] = 0;
      mySerial.write(output, sizeof(output));
      output_index = 0;
 
      return;
 
    } else if (*p == 'R') { // read
      p = strtok(NULL, " ");
      if (!SD.exists(p)) {
        memcpy(output + output_index, "No such file or directory!", sizeof("No such file or directory!"));
        output_index += sizeof("No such file or directory!");
 
        output[output_index] = 0;
        mySerial.write(output, sizeof(output));
        output_index = 0;
 
        return;
      }
 
      Serial.println(p);
      file = SD.open(p, FILE_READ);
 
      char c = 0;
      c = file.read();
      while (c != -1) {
        output[output_index++] = c;
        c = file.read();
      }
 
      file.close();
 
      output[output_index] = 0;
      mySerial.write(output, sizeof(output));
      output_index = 0;
 
      return;
 
    } else if (*p == 'W') { // write
      p = strtok(NULL, " ");
 
      Serial.println(p);
      file = SD.open(p, FILE_WRITE);
 
      p = strtok(NULL, " ");
 
      Serial.println(p);
      file.write(p, strlen(p));
 
      file.close();
 
      return;
 
    } else {
      Serial.println("lool");
      memcpy(output + output_index, "No such command!\n", sizeof("No such command!<br>"));
      output_index += sizeof("No such command!<br>");
 
      output[output_index] = 0;
      mySerial.write(output, sizeof(output));
      output_index = 0;
 
      return;
    }
  }
}
 
void loop() {
  char c;
 
  A0_value = analogRead(A0);
  if (A0_value > THRESHOLD) {
    c = kbd_buttons[second_half][0][kbd_button_index[A0_value / 100]];
 
    cmd[cmd_index++] = c;
 
    output[output_index++] = c;
    output[output_index] = 0;
    mySerial.write(output, sizeof(output));
  }
 
  A1_value = analogRead(A1);
  if (A1_value > THRESHOLD) {
    c = kbd_buttons[second_half][1][kbd_button_index[A1_value / 100]];
 
    cmd[cmd_index++] = c;
 
    output[output_index++] = c;
    output[output_index] = 0;
    mySerial.write(output, sizeof(output));
  }
 
  A2_value = analogRead(A2);
  if (A2_value > THRESHOLD) {
    c = kbd_buttons[second_half][2][kbd_button_index[A2_value / 100]];
 
    cmd[cmd_index++] = c;
 
    output[output_index++] = c;
    output[output_index] = 0;
    mySerial.write(output, sizeof(output));
  }
 
  A3_value = analogRead(A3);
  if (A3_value > THRESHOLD) {
    c = kbd_buttons[second_half][3][kbd_button_index[A3_value / 100]];
 
    switch (c) {
    case '/':
    case ' ':
      cmd[cmd_index++] = c;
 
      output[output_index++] = c;
      output[output_index] = 0;
      mySerial.write(output, sizeof(output));
 
      break;
 
    case '\n':
      output[output_index++] = '<';
      output[output_index++] = 'b';
      output[output_index++] = 'r';
      output[output_index++] = '>';
      output[output_index] = 0;
 
      cmd_exec();
      memset(cmd, 0, sizeof(cmd));
      cmd_index = 0;
      output_index = 0;
      memset(output, 0, sizeof(output));
 
      break;
 
    case '0':
      second_half ^= 1;
 
      analogWrite(9, second_half);
 
      break;
    }
  }
 
  delay(150);
}

Rezultate Obţinute

Proiectul functioneaza cum a fost intentionat. Astfel, interactionand cu tastatura din cei 16 push-buttons, un utilizator poate face I/O pe un SDCard. Desi am avut probleme cu LCD-ul si a trebuit sa il returnez, am reusit sa improvizez cu ajutorul unui server de web realizat cu ajutorul ESP8266. Utilizatorul isi poate vedea rezultatele actiunilor sale urmarind shell-ul expus in server-ul web care se actualizeaza la fiecare secunda.

Concluzii

Desi este un proiect relativ simplu, acesta poate veni la indemana cand, din motive oarecare, un utilizator nu are la indemana un laptop sau calculator sau pur si simplu se intampla sa aiba nevoia de a stoca ceva pe un mediu de stocare nonvolatil.

O aplicatie practica a acestui proiect ar putea fi un sistem integrat de Journaling.

Download

sd_card_buddy.zip

Jurnal

Bibliografie/Resurse

Resurse Software:

Resurse Hardware:

Export to PDF