Vline: Apricot

by Zubaydah in Circuits > Art

380 Views, 1 Favorites, 0 Comments

Vline: Apricot

Pr2.png
Pr1.png

Beschrijving

Ik ben dol op katten, echter heb ik er geen. Dus kwam ik op het idee om zelf een kattenvriendje in elkaar te zetten.

Vline (een woordspeling op 'feline') zijn digitale katachtige. Deze Vline heet Apricot.
Apricot is een digitale kat die reageert op aanraking. Hij heeft een knop op zijn hoofd waarmee je hem kan 'aaien'. Wanneer je de kat aait, wordt er een signaal verstuurt via de Arduino die de LED matrix activeer om tekst te laten verschijnen. De tekst verschijnt verticaal van boven naar beneden. Apricot heeft drie staten; niets, spinnen en sissen. Voor elke staat verschijnt er andere tekst. Apricot vind het niet prettig als je hem té veel aait. Dit heb ik gedaan zodat er meer interactie mogelijk met hem. Na een combo van tien keer aaien, gaat hij sissen. Hierna kan je hem weer rustig aaien.

Supplies

Elektronische componenten

  • Arduino Uno
  • Drukknop 12 x 12 x 7,3 mm (OF druksensor)
  • 9V Batterij
  • 9V Connector for Arduino
  • LED Matrix 32x8 met MAX7219 Module
  • Zeven male-female draden (dit is exclusief van de draden die je bij de LED Matrix krijgt)

Materialen voor de behuizing

  • MDF 45 x 45 cm
  • Witte verf
  • Zwarte stift
  • Karton (het liefst een sterke variant)

Gereedschap

  • Soldeerbout met soldeer
  • Lasersnijder
  • Striptang
  • Schaar
  • Lijmpistol
  • Boor
  • Tape

De Vormgeving

20220228_145948_SKETCHES.jpg
20220228_150031_SKETCHES2.jpg
V-Line Apricot Turnaround.png

Voordat ik aan de gang kan gaan met alles in elkaar zetten, heb ik een visie nodig van de vormgeving. Dus ben ik begonnen met schetsen. De kat moest er snoezig uitzien. Uit mijn schetsen is te zien dat ik een voorkeur had naar de rondere katten. Apricot verteld zijn gevoelens via de LED matrix, daarom gaf ik hem liever geen glimlach. Het zou niet kloppen als hij glimlacht terwijl de LED matrix zegt dat hij sist.
Een bewegende staart toevoegen die aangestuurd werd met een servo was ook een idee, maar dat heb ik uiteindelijk niet gedaan. Dat komt omdat ik het ontwerp ingewikkeld genoeg vond met de LED matrix.

Hierna ben ik een turn-around gaan schetsen van het uiteindelijke ontwerp. Met dit ontwerp was het plan om hem in 3D te modelleren en vervolgens te 3D printen. In dit ontwerp houdt Apricot een pootje in de lucht, net als een maneki neko. Met dit pootje houdt hij de LED matrix vast. Zo kon ik de draadjes van de LED matrix verstoppen in zijn arm. Hij is ook een beetje dik, dit is met opzet. Zo heb ik veel ruimte in zijn lichaam waar ik de Arduino en andere kabels in kwijt kan.

Prototyping

20220316_153439.jpg
20220316_133310.jpg
LED matrx test.gif
Druksensor reactie test.gif
20220316_154623.jpg
20220317_135446.jpg

Als eerste ben ik gaan kijken of ik de druksensor werkend kreeg op reactie. Dit ging ik testen door middel van een groen LED lampje die altijd aanstaat. Echter wanneer ik de druksensor zou aanraken, zou het lampje uitgaan. Daarna ben ik gaan spelen met de LED matrix. Ik moest eerst weten hoe ik het in mijn Arduino kon verbinden. Het komt namelijk met vijf kabels zonder duidelijke beschrijving waar ze naartoe moeten. Na wat onderzoek ben ik erachter gekomen dat het als volgt in de Arduino moet:

  • VCC in 5V
  • GND in GND
  • DIN in Digital 11
  • CS in Digital 10
  • CLK in Digital 13

Ik ben erachter gekomen dat je animaties kan laten tonen op de matrix en ook dat je tekst beide horizontaal en verticaal kan laten tonen.
Hierna heb ik de druksensor laten werken met de LED matrix i.p.v. het groene lampje. Zoals al eerder genoemd, heeft Apricot drie staten. De druksensor geeft een waarde bij de hoeveelheid druk in de seriële monitor. Dus wanneer je het niet aanraakt, geeft het een waarde van 0, een redelijk zachte druk is rond de 300 en een harde druk zou rond de 600 geven. Hiermee heb ik de drie verschillende staten mee kunnen aangeven.

Na de code schrijven, heb ik een prototype gemaakt van vormgeving. Zo kon ik ongeveer inschatten hoe groot mijn project werd.

3D Modeleren

Chonky.gif
3D model.png
V-Line Bedrading voor 3D model.png
unknown.png

Nu ik een idee had voor de vormgeving kon ik aan de gang gegaan met het maken van een 3D model in MAYA op schaal, met behulp van de turn-around. De Arduino Uno zou in zijn buik zitten samen met alles wat gesoldeerd moest worden. Op het plaatje is te zien hoe ik van plan was om de bedradingen in hem te verstoppen.

Ik ben een aantal dagen bezig geweest met het modelleren van het snoezige vriendje. Hierbij moest ik ook kijken hoe ik hem open kan maken. Het idee was om de onderkant open te laten en het hoofd van het lichaam af te kunnen schroeven. Tijdens mijn onderzoek om te kijken naar hoe ik delen van mijn 3D print kan openen en sluiten, ben ik achter het programma Fusion360 gekomen. Hiermee kan men threads maken aan twee cilinders en zo ontstaat er een schroeffunctie. Dit was mijn concept voor zijn nek, desalniettemin kwam ik tegen een probleem aan lopen: de threads die ik heb gemaakt in Fusion360 worden niet overgebracht in Preform of Cura. Dit heb ik opgelost door alleen het hoofdje een cilinder te geven, wat een beetje op een nek lijkt, zo schuift het hoofdje in het lichaam en valt het er niet uit.


Echter op het moment dat mijn 3D model klaar was om geprint te worden, kwam ik tegen een nog probleem lopen: het 3D printen zou over mijn budget gaan. Het was een té dure optie voor mij, dus ben ik gaan kijken voor alternatieven. Toen kwam ik achter papercraft en daarbij het programma Pepakura. Pepakura maakt een bouwtekening voor op een stuk papier dat vouwlijnen en plakranden bevat. Dit kan je uitprinten en vervolgens knippen, vouwen en ik elkaar plakken. Alleen hierbij was het probleem dat Apricot veel te fragiel zou zijn als hij uit papier gemaakt zou zijn.

Lasersnijden

20220613_140634.jpg
20220608_092943.jpg
20220608_092947.jpg
VLine-box.png

Op dit punt van mijn project zat ik in een dilemma: ga ik voor de vormgeving of de stabiliteit? Mijn voorkeur ging naar een stabiele project. Om dit te doen heb ik gekozen om de buitenkant te maken van MDF. Hiervoor heb ik een nieuw ontwerp gemaakt. Effectief en schattig is het idee erachter. Het is namelijk makkelijker om de bedrading van binnen netjes te maken in deze vorm.
Na het snijden heb ik een gat geboord aan de zijkant van de poes, hier zullen de draden van de LED matrix doorheen gaan.

Druksensor Solderen

20220607_111604.jpg
20220607_111611.jpg
20220607_134832.jpg
20220608_202722.jpg
20220610_163049.jpg
20220610_162030.jpg
20220610_162036.jpg
20220611_131153.jpg

Bij de eerste twee foto's is de stroomkring te zien met het behulp van een breadboard. Dit heb ik moeten uittekenen als een stroomkring, zodat ik het kan solderen. Ik heb schets nummer II gebruikt om te solderen.
Desalniettemin stopte hindernissen niet bij de vormgeving. Tijdens het solderen kwam ik ook tegen een aantal problemen aan. Het is lastig om te solderen op het soldeerbord dat bij het Arduino pakket kwam van het HKU, het tin werkte niet mee op dit stuk soldeerbord (het gele/oranje bord in de afbeeldingen) en de draden lieten steeds los. Vervolgens heb ik gesoldeerd op een ander bord (de zwarte soldeerbord in de afbeeldingen) met andere draden. Dit ging beter, omdat ik meer controle had over het tin op dit bord en de draden niet gelijk kapot gingen.

Toen ik dacht dat ik klaar was met solderen kwam ik tegen nog een probleem aan: mijn druksensor scheurde en werkte niet meer. Ik had geen tweede druksensor, dus dit betekende dat ik snel een alternatief moest verzinnen.

Drukknop Solderen

20220610_164814.jpg
sjZNV.png

De alternatief die ik bedacht had was een drukknop. Het concept is dat Apricot gaat snorren wanneer je op het knopje op zijn hoofd drukt in plaats van de druksensor. Hierbij hoefde ik ook niet te priegelen met een soldeerbord, maar kon ik de draden solderen aan de 2e en 4e uiteinde van de knop.

Om nog steeds de drie staten idee te houden, heb ik een "comboCounter" toegevoegd aan de code. Deze telt op hoe vaak je Apricot hebt geaaid. Als het meer dan negen is, gaat Apricot sissen.

Code

// By Zubaydah Koelemeij - ITTT project Vline: Apricot
//
// Use the Parola library to scroll text on the display
//
// Demonstrates the use of the scrolling function to display text received
// from the serial interface in a vertical display.
//
// User can enter text on the serial monitor and this will display as a
// scrolling message on the display.
// Speed for the display is controlled by a pot on SPEED_IN analog in.
// Scrolling direction is controlled by a switch on DIRECTION_SET digital in.
// Invert ON/OFF is set by a switch on INVERT_SET digital in.
//
// UISwitch library can be found at https://github.com/MajicDesigns/MD_UISwitch
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Parola_Fonts_data.h"

// set to 1 if we are implementing the user interface pot, switch, etc
#define USE_UI_CONTROL 0

#define FORCE_SENSOR_PIN A0

#if USE_UI_CONTROL
#include <MD_UISwitch.h>
#endif

// Turn on debug statements to the serial output
#define DEBUG 0

#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif

// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 11

#define CLK_PIN   13
#define DATA_PIN  11
#define CS_PIN    10

// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// Scrolling parameters
#if USE_UI_CONTROL
const uint8_t SPEED_IN = A5;
const uint8_t DIRECTION_SET = 8;  // change the effect
const uint8_t INVERT_SET = 9;     // change the invert

const uint8_t SPEED_DEADBAND = 5;
#endif // USE_UI_CONTROL

uint8_t scrollSpeed = 30;    // default frame delay value
textEffect_t scrollEffect = PA_SCROLL_LEFT;
textPosition_t scrollAlign = PA_CENTER;
uint16_t scrollPause = 0; // in milliseconds

// Global message buffers shared by Serial and Scrolling functions
#define	BUF_SIZE	75
char curMessage[BUF_SIZE] = { "" };
char newMessage[BUF_SIZE] = { "IF THIS THEN THAT" };
bool newMessageAvailable = true;

//These will act as start and stop signs for when a message should be displayed
bool nothingActive = false;
bool petActive = false;
bool petTooActive = false;

//comboCounter will count how many times you pet the cat.
int comboCounter = 0;

#if USE_UI_CONTROL

MD_UISwitch_Digital uiDirection(DIRECTION_SET);
MD_UISwitch_Digital uiInvert(INVERT_SET);

void doUI(void)
{
  // set the speed if it has changed
  {
    int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 10, 150);

    if ((speed >= ((int16_t)P.getSpeed() + SPEED_DEADBAND)) ||
        (speed <= ((int16_t)P.getSpeed() - SPEED_DEADBAND)))
    {
      P.setSpeed(speed);
      scrollSpeed = speed;
      PRINT("\nChanged speed to ", P.getSpeed());
    }
  }

  if (uiDirection.read() == MD_UISwitch::KEY_PRESS) // SCROLL DIRECTION
  {
    PRINTS("\nChanging scroll direction");
    scrollEffect = (scrollEffect == PA_SCROLL_LEFT ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);
    P.setTextEffect(scrollEffect, scrollEffect);
    P.displayClear();
    P.displayReset();
  }

  if (uiInvert.read() == MD_UISwitch::KEY_PRESS)  // INVERT MODE
  {
    PRINTS("\nChanging invert mode");
    P.setInvert(!P.getInvert());
  }
}
#endif // USE_UI_CONTROL

void readSerial(void)
{
  static char *cp = newMessage;

  while (Serial.available())
  {
    *cp = (char)Serial.read();
    if ((*cp == '\n') || (cp - newMessage >= BUF_SIZE - 2)) // end of message character or full buffer
    {
      *cp = '\0'; // end the string
      // restart the index for next filling spree and flag we have a message waiting
      cp = newMessage;
      newMessageAvailable = true;
    }
    else  // move char pointer to next position
      cp++;
  }
}

int button = 2;

void setup()
{
  Serial.begin(57600);
  Serial.print("\n[Parola Scrolling Display]\nType a message for the scrolling display\nEnd message line with a newline");

  pinMode(A0, INPUT);

  //Button input reading
  pinMode(button, INPUT);
  digitalWrite(button, HIGH);

#if USE_UI_CONTROL
  uiDirection.begin();
  uiInvert.begin();
  pinMode(SPEED_IN, INPUT);

  doUI();
#endif // USE_UI_CONTROL

  P.begin();
  P.setFont(_fontVertical);
  P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
}

void loop()
{
#if USE_UI_CONTROL
  doUI();
#endif // USE_UI_CONTROL

  int analogReading = analogRead(FORCE_SENSOR_PIN);

    if(digitalRead(button) == HIGH && nothingActive == false){
      Serial.println(" -> Nothing"); //Nothing should appear here. Otherwise the cat will think it's getting pet when nothing's happening
      P.displayText("...", scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
      nothingActive = true;
      petActive = false;
      petTooActive = false;
      delay(20);
    }
  
  else if(digitalRead(button) == LOW && petActive == false && comboCounter < 10){
      Serial.println(" -> Gently petting..."); //Whenever you press the button, you are gently petting
      P.displayText("purrr...", scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
      petActive = true;
      nothingActive = false;
      petTooActive = false;
      delay(20);
      comboCounter += 1;
      Serial.println(comboCounter);
    }

    else if(digitalRead(button) == LOW && petActive == true && comboCounter > 9){
        Serial.println(" -> OUCH!"); //If you pet the cat fast for 10 times, the cat won't like that. It'll hiss at you.
        P.displayText("HISSSS", scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
        petTooActive = true;
        nothingActive = false;
        petActive = true;
        delay(20);
        comboCounter = 0;
      }


// Everything below this part would be used if you would use a pressure sensor instead of a button.  
//  if (analogReading < 10 && nothingActive == false)
//  {
//    Serial.println(" -> Nothing"); //Nothing should appear here. Otherwise the cat will think it's getting pet when nothing's happening
//    P.displayText("...", scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
//    nothingActive = true;
//    petActive = false;
//    petTooActive = false;
//    delay(20);
//  }
//  else if (analogReading > 20 && analogReading < 550 && petActive == false)
//  {
//    Serial.println(" -> Gently petting..."); //Only below 600 is considered a pleasant, gentle petting
//    P.displayText("purrr...", scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
//    petActive = true;
//    nothingActive = false;
//    petTooActive = false;
//    delay(20);
//  }
//  else if (analogReading > 600 && petTooActive == false)
//  {
//    Serial.println(" -> OUCH!"); //Anything above 600 is too harsh, the cat won't like that
//    P.displayText("HISSSS", scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
//    petTooActive = true;
//    nothingActive = false;
//    petActive = false;
//    delay(20);
//  }

  if (P.displayAnimate())
  {
    if (newMessageAvailable)
    {
      strrev(newMessage);   // reverse the string for proper display order
      strcpy(curMessage, newMessage);
      newMessageAvailable = false;
    }
    P.displayReset();
  }

  readSerial();
}

Het Bouwen Afmaken

20220608_103707.jpg
20220611_145429.jpg
20220611_174818.jpg
20220611_145230 (1).jpg

Nu dat de code werkt, moet de rest van de vormgeving afgemaakt worden. Ik ben begonnen door elk individueel stuk MDF te verven met witte verf. Ik had meerdere lagen geverfd, zodat de witte kleur meer naar voren kwam. Na het verven, heb ik de binnenkant gemaakt van karton. Ik moest zeker zijn dat niets uit zijn plaats zou vallen tijdens het reizen naar school. Om hiervoor te zorgen heb een soort bedje gemaakt voor Arduino zelf, samen met een kast wat de draden begeleid. Daarbij heeft de batterij ook zijn eigen doosje. Alles is vastgezet met hete lijm.

Conclusie

Vline: Apricot

Tijdens dit project heb ik informatie opgebouwd over solderen, 3D printen, lasersnijden en coderen. Om netjes te solderen moet je een aantal stappen nemen. Het van belang dat je een kloppende circuit hebt, anders moet je opnieuw beginnen met solderen. Ook moet je niet meer tin gebruiken dan nodig is. Daarbij heb ik geleerd hoe ik een model maak voor de 3D printer, hoe ik moet 3D printen en dat het een betere optie is voor kleinere modellen. Als je grote modellen wil gaan printen, wordt het duur. Het was een leerzaam maar ook frustrerend project, omdat elke keer dat ik dacht dat ik klaar was met een stap, liep ik tegen een probleem aan. Ik ben gelukkig dat ik een alternatief heb kunnen vinden voor mijn druksensor, dat was namelijk een belangrijk stuk van mijn project. Maar alle moeite voelt het compleet waard nu dat ik een werkend eindproduct heb.