ESP-WROOM-32

Der neue MicroShip der von der Firma Espressif Systems entwickelt wurde, ist seit einigen Monaten am Markt und bringt eine Menge neue Futures mit.
Eine der angenehmeren Möglichkeiten mit dem [wiki]ESP32[/wiki] ein Projekt umzusetzen, ist das verwenden von “MicroPython”. In Verbindung mit dem “Atom” Editor und dem “pymakr” PlugIn.

ESP32

Snippets

WeMos D1 R32 Uno mit 2.6″/2.8″TFT LCD Shield

SD-Card (SPI / on Shield)

SS – CS – 05
SCK – CLK – 18
DO – MISO – 19
DI – MOSI – 23

LCD_TFT (2.6″/2.8″TFT LCD Shield)

LCD_RST – LCD_Reset – 36
LCD_CS – ChipSelect – 34
LCD_RS – (RegisterSelect) – 35
LCD_WR – (WRite data) – 04
LCD_RD – (ReaD data) – 02

LCD_D0 – 12
LCD_D1 – 13

LCD_D2 – 26
LCD_D3 – 25
LCD_D4 – 17
LCD_D5 – 16
LCD_D6 – 27
LCD_D7 – 14

WiKi / Infos zum Shield: 2.6″ / 2.8″ TFT_LCD

>>> import gc

>>> gc.collect()

>>> gc.mem_free()

90208

>>> import uos

>> uos.uname()

(sysname=‘esp32’, nodename=‘esp32’, release=‘1.9.3’, version=‘v1.9.3-240-ga275cb0f on 2018-01-27’, machine=‘ESP32 module with ESP32’)

>>>

SPI / ESP32 / MicroPython
Serial Peripheral Interface

… ist ein Protokoll um zwischen 2 Geräten Daten in beide Richtungen zu senden.
Als Beispiel: Ein LED-Controller bekommt Informationen/Daten gesendet um zu wissen was er tun soll. Hingegen ein Temperatursensor schickt Daten an den Microkontroller.

Und so läuft das Spiel:


Der SPI Master:

Im SPI Protokoll gibt es einen wesentlichen Unterschied zwischen dem Master, der die Verbindung kontrolliert und steuert, und dem Slave der Daten von und zum Master sendet und empfängt.
In allen Fällen ist der Microkontroller der Master und steuert die SPI Verbindung.
In dem folgenden Beispiel wollen wir einmal ausprobieren wie der ESP32 mit Hilfe von MicroPython die SPI Verbindung mit anderen Geräten steuert.
 
In den meisten Fällen braucht eine SPI Verbindung mindestens 4 Leitungen um sich zu verbinden.
 
  • Clock, das SPI Master Gerät schaltet diese Leitung auf “I oder 0” um der Gegenstelle (Slave) zu sagen wann sie senden und wann sie empfangen soll/darf.
  • MOSI (master output, slave input), über diese Leitung werden Daten vom Master an ein Slave-Gerät gesendet. Das ist quasi der Datenausgang vom Master-Gerät.
  • MISO (master input, slave output), Über diese Leitung senden die Slave-Geräte ihre Daten an den Master (Microkontroller). Also der wenn man so will ist das der Daten-Ausgang der Slave-Geräte.
  • Chip Select (CS), auch wenn es nicht nötig ist, haben die meistern SPI Geräte eine CS-Leitung. Über diese Leitung kann der Master (mit I oder 0) den angeschlossenen Slave-Geräten mitteilen ob sie gerade auf SPI-Befehle hören sollen oder nicht. So lange alle angeschlossenen SPI-Geräte an eine SC Leitung angeschlossen sind, können sie sich die anderen Leitungen (Clock, MOSI und MISO) teilen. So kann jedes Gerät einzeln angesprochen werden.
Allerdings solltest Du dir bewusst sein, dass bei den unterschiedlichen Boards(Controllern), auf denen MicroPythen läuft, die SPI API beim erstellen des Master Mode unterschiedliche Wege kennt.
 
 
 

ADC Messung in C programmieren

Einzelmessung und Mehrfachmessung mit Mittelwert

// ADC initialisieren
void ADC_Init(void)
{
    unsigned int result;
   
*********************************************************************************
*********************************************************************************  

    ADMUX = (0<<REFS1) | (1<<REFS0);            // AVcc als Referenz benutzen
    // Teiler 128 da wir genau messen möchten
    ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);  // Frequenzvorteiler 128
    ADCSRA |= (1<<ADEN);         // ADC aktivieren
    ADCSRA |= (1<<ADSC);                      // Single ADC-Wandlung start
    while (ADCSRA & (1<<ADSC));               // auf Abschluss der Konvertierung warten
   
    // ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen.
    result = ADCW;
}

// ADC Einzelmessung
unsigned int ADC_Read(unsigned char channel)
{
    // Kanal waehlen, ohne andere Bits zu beeinflußen
    ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
    ADCSRA |= (1<<ADSC);            // eine Wandlung “single conversion”
    while (ADCSRA & (1<<ADSC))      // auf Abschluss der Konvertierung warten
    //return ADCW;                  // ADC auslesen und zurückgeben
    return ADCL + (ADCH<<8);
}

// ADC Mehrfachmessung mit Mittelwertbbildung 50ms!
unsigned int ADC_Read_Avg(unsigned char channel, unsigned char average)
{
    unsigned long result = 0;
   
    for (unsigned char i = 0; i < average; ++i)
    {
        result += ADC_Read(channel);
        _delay_ms(50);
    }
   
    return (unsigned int)(result / average);
}

*********************************************************************************
*********************************************************************************

Serielle Ausgabe (UART) in C geschrieben

*********************************************************************************
*********************************************************************************

// Geschwindigkeit der CPU (16MHz)
#define F_CPU 16000000UL

// Baudrate (19200 Baud)
#define BAUD 19200UL

// Baudratenberechnung
#define UBRR_VAL ((F_CPU+BAUD*8) / (BAUD*16)-1)

#include <avr/io.h>
#include <util/delay.h>

// UART-Init ATmega328P
void uart_init(void)
{
    // Baudrate einstellen
    UBRR0H = (unsigned char)(UBRR_VAL>>8);
    UBRR0L = (unsigned char)UBRR_VAL;
   
    // Receiver und Transmitter einschalten
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
   
    // Frame Format: Asynchron 8N1
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
}

// Charakter schreiben
void uart_putChar(unsigned char c)
{
    // Warten bis Sendepuffer leer ist
    while (!(UCSR0A & (1<<UDRE0)));
   
    // Daten in den Puffer schreiben und senden
    UDR0 = c;
}

// String senden
void uart_putStr(unsigned char *s)
{
    while (*s)
    { 
        // so lange *s != ‘�’ also ungleich dem “String-Endezeichen(Terminator)”
        uart_putChar(*s);
        s++;
    }
}

*********************************************************************************
*********************************************************************************

Hier ein Beispielcode:

[code]
#include <Wire.h> //I2C Arduino Library

#define addr 0x1E //I2C Address for The HMC5883

void setup(){
 
  Serial.begin(9600);
  Wire.begin();
 
 
  Wire.beginTransmission(addr); //start talking
  Wire.write(0x02); // Set the Register / Das Register auswählen
  Wire.write(0x00); // Tell the HMC5883 to Continuously Measure
  Wire.endTransmission();
 
}

void loop(){
 
  int x,y,z; // Daten der 3 Achsen
  int s; // Status
  char id, id1, id2; // Identification Register A, B, C
 
  //Tell the HMC what regist to begin writing data into
  Wire.beginTransmission(addr);
  Wire.write(0x03); //start with register 3.
  Wire.endTransmission();
 

 // Lesen der 3 Achsen, je 2x 8bit (3x 2 Register)
  Wire.requestFrom(addr, 6); // Anfrage an Gerät (addr) für 6 bytes
  if(6<=Wire.available()){
    x = Wire.read()<<8; //MSB  x
    x |= Wire.read(); //LSB  x
    z = Wire.read()<<8; //MSB  z
    z |= Wire.read(); //LSB z
    y = Wire.read()<<8; //MSB y
    y |= Wire.read(); //LSB y
  }

  // Lesen von Status und IDs
  Wire.beginTransmission(addr);
  Wire.write(0x09); // Starten mit Register 9
  Wire.endTransmission();
  Wire.requestFrom(addr, 4);
  if(4<=Wire.available()){

    s = Wire.read();
    id = Wire.read();
    id1 = Wire.read();
    id2 = Wire.read();

  }
    float heading = atan2(-y, x);
    float declinationAngle = 39.85/1000;
   
    heading += declinationAngle;

    float headingDegrees = heading * RAD_TO_DEG;
    if (headingDegrees < 0) headingDegrees += 360;
  
   delay(100);

 
  // Daten ausgeben
  Serial.println(“*****************************”);
  Serial.print(“Kompass Grad: “);
  Serial.println(headingDegrees);
  Serial.print(“X Value: “);
  Serial.println(x);
  Serial.print(“Y Value: “);
  Serial.println(y);
  Serial.print(“Z Value: “);
  Serial.println(z);
  Serial.println();
  Serial.print(“Status: “);
  Serial.println(s, DEC);
  Serial.println();
  Serial.print(“ID-A: “);
  Serial.println(id);
  Serial.print(“ID-B: “);
  Serial.println(id1);
  Serial.print(“ID-C: “);
  Serial.println(id2);
  Serial.println(“*****************************”);
 
  delay(500);
}
[/code]

Die Komponenten für den Prototypen:

  • China RoboCar Chassis inkl. DC Getriebemotoren 5V mit Encoderrad und 4x AA Batteriefach
  • UltraschallSensor HC-SR04
  • L298N Dual Motor Controller Module 2A
  • Arduino UNO
  • ProtoShield for Arduino UNO
  • 2x Gabellichtschranken
Chassis mit Aufbau
 
 
 
 
 
Motoren mit Encoderrad und Batteriehalter 4x AA (6V)

 

Schaltung für die Gabellichtschranken (blau – GND / orange – +5V / schwarz – GRD / Signal I/O – Dig.PIN 2 und 3)  
 

 

 
Was später geändert wird:
  • Der Arduino wird gegen einen ArduinoMicro getauscht
  • Das Batteriefach gegen einen größeren Akku bzw. eine PowerBank
  • Es kommen weitere Kontakt-/Abstandssensoren

Wenn sichergestellt ist, das die Basis so funktioniert wie sie soll, wir das Projekt auf eine entsprechende Mechanik übertragen.

Der Code für den Arduino bis jetzt:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 


// PINs for UltraSonic#define pingPin 10
#define inPin 8

// PINs for Motor 1 DIR#define wheel_R_f 6
#define wheel_R_b 7

// PINs for Motor 2 DIR
#define wheel_L_f 12
#define wheel_L_b 13

// PINs for Motor 1 Enable/Speed (PWM)#define wheel_R_En 5
// PINs for Motor 2 Enable/Speed (PWM)
#define wheel_L_En 11

// Motorspeedint mspeed = 150;

// Turning circleint turnAround = 100;

// Current directionint currentDir = 0;

// Encoder#define Encoder_R 2
int EncoderCount_R = 0;
#define Encoder_L 3
int EncoderCount_L = 0;

// Setup Serial, Encoder- and MototrPINsvoid setup() {

pinMode(wheel_R_f, OUTPUT);
pinMode(wheel_R_b, OUTPUT);
pinMode(wheel_L_f, OUTPUT);
pinMode(wheel_L_b, OUTPUT);
pinMode(wheel_R_En, OUTPUT);
pinMode(wheel_L_En, OUTPUT);

// Setup EncoderpinMode(Encoder_R,INPUT);
pinMode(Encoder_L,INPUT);
attachInterrupt(0, isr_Encoder_R, CHANGE);
attachInterrupt(1, isr_Encoder_L, CHANGE);
//All Motors STOPmstop();

// Robo goes forwardgoforward();
}

void loop()
{

// establish variables for duration of the ping,
// and the distance result in centimeters:
long duration, cm;

// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);

// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(inPin, INPUT);
duration = pulseIn(inPin, HIGH);

// convert the time into cmcm = microsecondsToCentimeters(duration);

// *******************************************************************************
// If the Ultrasonic Sensor detect an object whith a disstance smaler then 15cm,
// stop than go backward for 150ms, turn around 180°, stop, than go forward againif (cm < 15)
  {
    mstop();
    gobackward();
    delay(1000);
    gobackwardCL();
  //  delay(2500);
    mstop();
    CountReset();
    goforward();
  }

// Automatically synchronize the speed of the wheelsif (EncoderCount_L < EncoderCount_R)
{
  analogWrite(wheel_R_En, mspeed-20);
  analogWrite(wheel_L_En, mspeed+20);
}

if (EncoderCount_R < EncoderCount_L)
{
  analogWrite(wheel_R_En, mspeed+20);
  analogWrite(wheel_L_En, mspeed-20);
}

delay(100);
}
// *******************************************************************************
long microsecondsToCentimeters(long microseconds)
{

// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}

// Function: All Motors STOPvoid mstop ()
{
  digitalWrite(wheel_R_b, LOW);
  digitalWrite(wheel_L_b, LOW);
  digitalWrite(wheel_R_f, LOW);
  digitalWrite(wheel_L_f, LOW);
  analogWrite(wheel_R_En, 0);
  analogWrite(wheel_L_En, 0);

currentDir = 0;

  delay(500);

}

// Function: All Motors go forwardvoid goforward ()
{
  digitalWrite(wheel_R_f, HIGH);
  digitalWrite(wheel_L_f, HIGH);
  digitalWrite(wheel_R_b, LOW);
  digitalWrite(wheel_L_b, LOW);

currentDir = 1;

  for (int ispeed = 100; ispeed <= mspeed; ispeed=ispeed+2)
  {
    analogWrite(wheel_R_En, ispeed);
    analogWrite(wheel_L_En, ispeed);
    delay(20);
  }
 
}

// Function: All Motors go backwardvoid gobackward ()
{
  digitalWrite(wheel_R_f, LOW);
  digitalWrite(wheel_L_f, LOW);
  digitalWrite(wheel_R_b, HIGH);
  digitalWrite(wheel_L_b, HIGH);

currentDir = 2;
 
  for (int ispeed = 100; ispeed <= mspeed; ispeed=ispeed+2)
  {
    analogWrite(wheel_R_En, ispeed);
    analogWrite(wheel_L_En, ispeed);
    delay(20);
  }

}

// Function: Go in a backward-circle to the leftvoid gobackwardCL ()
{
  digitalWrite(wheel_R_f, HIGH);
  digitalWrite(wheel_L_f, LOW);
  digitalWrite(wheel_R_b, LOW);
  digitalWrite(wheel_L_b, HIGH);

currentDir = 3;

CountReset();
 
  for (int ispeed = 100; ispeed <= mspeed; ispeed=ispeed+2)
  {
    analogWrite(wheel_R_En, ispeed);
    analogWrite(wheel_L_En, ispeed);
    delay(20);
  }

do
{
  if (EncoderCount_R >= turnAround)
    analogWrite(wheel_R_En, 0);

  if (EncoderCount_L >= turnAround)
    analogWrite(wheel_L_En, 0);

} while (EncoderCount_R < turnAround && EncoderCount_L < turnAround);

 
}

// Function: Go in a backward-circle to the rightvoid gobackwardCR ()
{
  digitalWrite(wheel_R_f, LOW);
  digitalWrite(wheel_L_f, HIGH);
  digitalWrite(wheel_R_b, HIGH);
  digitalWrite(wheel_L_b, LOW);

currentDir = 4;

CountReset();
 
  for (int ispeed = 100; ispeed <= mspeed; ispeed=ispeed+2)
  {
    analogWrite(wheel_R_En, ispeed);
    analogWrite(wheel_L_En, ispeed);
    delay(20);
  }

do
{
  if (EncoderCount_R >= turnAround)
    analogWrite(wheel_R_En, 0);

  if (EncoderCount_L >= turnAround)
    analogWrite(wheel_L_En, 0);
 
} while (EncoderCount_R < turnAround && EncoderCount_L < turnAround);
 
}

// Reset the EncoderCounts (left and right)void CountReset()
{
  EncoderCount_L = 0;
  EncoderCount_R = 0;
}

// ISR – Encoder rightvoid isr_Encoder_R ()
{
   EncoderCount_R++;
}

// ISR – Encoder leftvoid isr_Encoder_L ()
{
   EncoderCount_L++;
}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Vielen Dank für den Code der den Ultraschallsensor belebt geht an: http://www.robodino.de/2011/12/ultraschall-distanz-sensor-hc-sr04.html

 Tutorial/Beispiel für die Verwendung eines TouchScreen mit einem ARDUINO Mega

Als externes SubMenue für eine CNC Fräse o.ä.

Bezugsquelle z.B.: https://eckstein-shop.de/32-inch-240×320-TFT-LCD-Display-mit-resistiveTouch-panel-fuer-Arduino

Arduino Library / Bibliothek hier gefunden:  MCUFried TFT Display UNO y MEGA libraries.zip
ggf. auch hier – http://www.smokeandwires.co.nz/blog/a-2-4-tft-touchscreen-shield-for-arduino/


Ein Beispiel:
(Eine Push-Button-Oberfläche zum abfragen der digitalen Eingänge (InPort) mit einem PULLUP über Masse geschaltet und schalten der digitalen Ausgänge (OutPort).

[code]
// TFT size is 240×320
// Found * ILI9341 * LCD driver
// ———————————————-
// Befehle Beispiele:

// tft.reset();

// uint16_t identifier = tft.readID();
// tft.begin(identifier);
// tft.setRotation(rotation);     – die Ausrichtung (0-3)
// tft.fillScreen(BLACK);     – farbig füllen (in HEX)
// tft.setCursor(0, 0);       – Curser Position setzen
// tft.setTextColor(WHITE);   – Textfarbe (in HEX)
// tft.setTextSize(1);        – Textgröße
// tft.println(“Hello World!”);     – Text
// tft.drawLine(x1, y1, x2, y2, color);     – Linie von x,y nach x,y in Farbe (in HEX)
// tft.drawFastHLine(0, y, w, color1);      – horizontale Linie von x,y mit Länge in Farbe (in HEX)
// tft.drawFastVLine(x, 0, h, color2);      – vertikale Linie von x,y mit Länge in Farbe (in HEX)
// cx = tft.width();      – TFT Breite
// cy = tft.height();     – TFT Höhe
// tft.drawRect(cx-i2, cy-i2, i, i, color);     – Rechteck von Ecke x,y zur Ecke x,y in Farbe (in HEX)
// tft.fillRect(cx-i2, cy-i2, i, i, color1);      – gefülltes Rechteck von Ecke x,y zur Ecke x,y in Farbe (in HEX)
// tft.fillCircle(x, y, radius, color);     – gefüllter Kreis Mittelpunkt x,y mit Radius in Farbe (in HEX)
// tft.drawCircle(x, y, radius, color);     – Kreis Mittelpunkt x,y mit Radius in Farbe (in HEX)
// tft.drawTriangle(                        – Dreieck
//      cx    , cy – i, // peak
//      cx – i, cy + i, // bottom left
//      cx + i, cy + i, // bottom right
//      tft.color565(0, 0, i));

// tft.fillTriangle(cx, cy – i, cx – i, cy + i, cx + i, cy + i,     – gefülltes Dreieck

//      tft.color565(0, i, i));

// tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 0, 0));     – Rechteck mit runden Ecken

// tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));     – gefülltes Rechteck mit runden Ecken





#include <Adafruit_GFX.h>    // Core graphics library

#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <TouchScreen.h>

#define LCD_CS A3 // Chip Select goes to Analog 3

#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino’s reset pin


#define YP A3  // must be an analog pin, use “An” notation!

#define XM A2  // must be an analog pin, use “An” notation!
#define YM 9   // can be a digital pin
#define XP 8   // can be a digital pin

#define TS_MINX 180 //150

#define TS_MINY 200  //120
#define TS_MAXX 920 //920
#define TS_MAXY 940 //940

// For better pressure precision, we need to know the resistance

// between X+ and X- Use any multimeter to read it
// For the one we’re using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 150);

#define  BLACK   0x0000

#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);


#define BOXSIZE 80

#define PENRADIUS 3

#define MINPRESSURE 10

#define MAXPRESSURE 1000

#define BOX_COLORE_ON GREEN

#define BOX_COLORE_OFF RED

#define FRAME_COLORE_ON BLUE

#define FRAME_COLORE_OFF BLACK

#define TEXT_COLORE_ON BLACK

#define TEXT_COLORE_OFF WHITE


// ——————————————–

// define Title
// ——————————————–
String Title[4][3] = {
  {“AIR”,”WATER”,”BRUSH”},
  {“VAC”,”LIGHT”,”T3″},
  {“a1″,”a2″,”a3”},
  {“b1″,”b2″,”b3”}
};


// ——————————————–

// define GCode
// ——————————————–
String GCode[4][3] = {
  {“M8″,”M7″,”M9”},
  {“T1″,”T2″,”T3”},
  {“a1″,”a2″,”a3”},
  {“b1″,”b2″,”b3”}
};


// ——————————————–

// define uTitle
// ——————————————–
String uTitle[4][3] = {
  {“ON/OFF”,”ON/OFF”,”ON/OFF”},
  {“ON/OFF”,”ON/OFF”,”ON/OFF”},
  {“ON/OFF”,”ON/OFF”,”ON/OFF”},
  {“ON/OFF”,”ON/OFF”,”ON/OFF”}
};


// ——————————————–

// define default Status 
// ——————————————–
boolean Status[4][3] = {
  {0,0,0},
  {0,0,0},
  {0,0,0},
  {0,0,0}
};


// ——————————————–

// define default InPutStatus 
// ——————————————–
boolean inputStatus[4][3] = {
  {1,1,1},
  {1,1,1},
  {1,1,1},
  {1,1,1}
};




// ——————————————–

// define In Port 
// ——————————————–
int inPort[4][3] = {
  {52,50,48},
  {46,44,42},
  {40,38,36},
  {34,32,30}
};


// ——————————————–

// define Out Port 
// ——————————————–
int outPort[4][3] = {
  {53,51,49},
  {47,45,43},
  {41,39,37},
  {35,33,31}
};




void setup() {


  //Temp 5V Ausgang:

//  pinMode(22, OUTPUT);
//  digitalWrite(22, 1);

uint16_t identifier = tft.readID();


Serial.begin(9600);


  tft.reset();


  tft.begin(identifier);


  tft.setRotation(3);

InitScreen();


// Init PINs

pinMode(13, OUTPUT);


}






//——————————————–

// MAIN
//——————————————–
void loop() {

  digitalWrite(13, HIGH);

  TSPoint p = ts.getPoint();
  digitalWrite(13, LOW);

  // if sharing pins, you’ll need to fix the directions of the touchscreen pins

  //pinMode(XP, OUTPUT);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  //pinMode(YM, OUTPUT);

  inWatcher();

    
    if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {

      int Box_y;

      int Box_x;

        // scale from 0->1023 to tft.width

        p.x = tft.height()-(map(p.x, TS_MINX, TS_MAXX, tft.height(), 0));
        p.y = tft.width()-(map(p.y, TS_MINY, TS_MAXY, tft.width(), 0));

        Box_x = xBox(p.x);

        Box_y = yBox(p.y);
      
      pushButton(Box_x,Box_y);
    }

}




int xBox(int p_x){


  int box;


        if (p_x < BOXSIZE*1) {

        box = 0;
      }


     else if (p_x < BOXSIZE*2) {

        box = 1;
      }


     else if (p_x < BOXSIZE*3) {

        box = 2;
      }

  return box;

  
}



int yBox(int p_y) {

  
  int box;

  if (p_y < BOXSIZE*1) {

    box = 3; }
  else if (p_y < BOXSIZE*2) {
    box = 2; }
  else if (p_y < BOXSIZE*3) {
    box = 1; }
  else if (p_y < BOXSIZE*4) {
    box = 0; }

// DEBUG

//  Serial.print(“P_Y = “); Serial.println(p_y);
//  Serial.print(“box = “); Serial.println(box);
//  Serial.print(“BOXSIZE = “); Serial.println(BOXSIZE);

  return box;

}



void pushButton(int x, int y) {


switchOutput(y, x, !Status[y][x]);


    delay(500);

  
}



void InitScreen() {

  // ——————————————–
// InitScreen
// ——————————————–


tft.fillScreen(BLACK);

  
  for (int y=0; y<4; y++)
  {
    for (int x=0; x<3; x++)
    {

    pinMode(inPort[y][x], INPUT_PULLUP);

    pinMode(outPort[y][x], OUTPUT);

    inputStatus[y][x] = digitalRead(inPort[y][x]);

    switchOutput(y, x, !inputStatus[y][x]);

    }

  }
}




void inWatcher(){


  for (int y=0; y<4; y++)

  {
    for (int x=0; x<3; x++)
    {
      boolean watchStatus;
      watchStatus = digitalRead(inPort[y][x]);
      
      if (!(watchStatus == inputStatus[y][x])) {
        
        inputStatus[y][x] = !inputStatus[y][x];

        switchOutput(y, x, !inputStatus[y][x]);


      }

    }
  }

}




void switchOutput(int y, int x, boolean on) {


  digitalWrite(outPort[y][x], on);

  Status[y][x] = on;

          if (on == 0)

            tft.fillRect(BOXSIZE*y, BOXSIZE*x, BOXSIZE, BOXSIZE, BOX_COLORE_OFF), tft.setTextColor(TEXT_COLORE_OFF);
          else if (on == 1)
            tft.fillRect(BOXSIZE*y, BOXSIZE*x, BOXSIZE, BOXSIZE, BOX_COLORE_ON), tft.setTextColor(TEXT_COLORE_ON);

          if (inputStatus[y][x] == 0)

            tft.drawRect(BOXSIZE*y, BOXSIZE*x, BOXSIZE, BOXSIZE, FRAME_COLORE_ON);
          else if (inputStatus[y][x] == 1)
            tft.drawRect(BOXSIZE*y, BOXSIZE*x, BOXSIZE, BOXSIZE, FRAME_COLORE_OFF);

          tft.setCursor(BOXSIZE*y+5, BOXSIZE*x+10);

          tft.setTextSize(2);
          tft.println(Title[y][x]);
          tft.setCursor(BOXSIZE*y+5, BOXSIZE*x+35);
          tft.println(GCode[y][x]);
          tft.setCursor(BOXSIZE*y+5, BOXSIZE*x+60);
          tft.setTextSize(1);
          tft.println(uTitle[y][x]);
}



[/code]



Ein kleines Beispiel wie ihr mit dem Monster Motor Shield 2 Motoren ansteuern könnt:

[code]
/*
 * Das Monster Motor Shield kann mit diesem Sketch über den Seriellen Monitor gesteuert werden.
 * Einfach den Speed und die Richtung durch ein Komma getrennt eingeben.
 * Beispiel: 100,1
 * Dann drehen die Motoren mit der Geschwindigkeit 100 von 255 gegen den Uhrzeigersinn
 * Mögliche Werte:
 * Speed – 0 bis 255 (0 = Stop, 255 = volle Geschwindigkeit)
 * Richtung(Dir) – 0 bis 3 (0 = im Uhrzeigersinn, 1 = gegen den Uhrzeigersinn, 2 = Motoren drehen gegeneinander,
 * 3 = Motoren drehen umgekehrt gegeneinander)
 * Bei einem Fahrzeug mit 2 Motoren wäre das dann:
 * 0 = Vorwärts
 * 1 = Rückwärts
 * 2 = nach links drehen
 * 3 = nach rechts drehen
 *
 * VNH2SP30 pin definitions
 * inApin[2] = {7, 4};  // INA: Clockwise input
 * inBpin[2] = {8, 9}; // INB: Counter-clockwise input
 * pwmpin[2] = {5, 6}; // PWM input
 * cspin[2] = {2, 3}; // CS: Current sense ANALOG input
 * enpin[2] = {0, 1}; // EN: Status of switches output (Analog pin)
 *
 * http://arduinoinc.blogspot.de/
 */

#define CS_THRESHOLD 15   // Der max Strom der durch den Treiber auf Dauer unterstützt wird

int inApin[2] = {7, 4}; // IN-A: Im Uhrzeigersinn drehen, Motor0 and Motor1 (Check:”1.2 Hardware Monster Motor Shield”).
int inBpin[2] = {8, 9}; // IN-B: Gegen den Uhrzeigersinn drehen, Motor0 and Motor1 (Check: “1.2 Hardware Monster Motor Shield”).
int pwmpin[2] = {5, 6};            // PWM’s input
int cspin[2] = {2, 3};              // Strom (A) Sensoren Motor 1/2

int statpin = 13;

int i=0;
int speedon = 0;
int speedaktuell = 0;
int dir = 0;
int diraktuell = 0;

void setup()                        
{
  Serial.begin(9600);
  Serial.println(“Ready to start – Speed,Dir”);
 
  pinMode(statpin, OUTPUT);
 
  for (int i=0; i<2; i++)
      {
        pinMode(inApin[i], OUTPUT);
        pinMode(inBpin[i], OUTPUT);
        pinMode(pwmpin[i], OUTPUT);
      }
     
  for (int i=0; i<2; i++)
      {
        digitalWrite(inApin[i], LOW);
        digitalWrite(inBpin[i], LOW);
      }
}

// **************************************************************

void loop()                         
{

  // Serielle Schnittstelle auslesen
  if (Serial.available() > 0)
  {
      // nach durch “,” getrennte Werte lesen
      speedon = Serial.parseInt();
      dir = Serial.parseInt();
     
      if (Serial.read() == ‘n’)     // nach dem Ende der Zeile schauen
      {
        // Die Werte auf bestimmte Bereiche beschränken
        speedon = constrain(speedon, 0, 255);
        dir = constrain(dir, 0, 3);
      }
     
      Serial.println(“Start”);
      Serial.print(“SpeedOn = “);
      Serial.println(speedon, DEC);
      Serial.print(“Dir = “);
      Serial.println(dir, DEC);
  }
       
 
 
  beschleunigen(speedon, dir);
 
 
 
 
 
  // Auf neue Werte/Anweisungen warten und Überprüfen ob der motor nicht blockiert ist
 
  while(i!=0)
  {                                     
      if (Serial.available() > 0)
      {
        speedon = Serial.parseInt();
        dir = Serial.parseInt();
       
        if (Serial.read() == ‘n’)
        {
            speedon = constrain(speedon, 0, 255);
            dir = constrain(dir, 0, 3);
        }
       
        Serial.print(“SpeedOn = “);
        Serial.println(speedon, DEC);
        Serial.print(“Dir = “);
        Serial.println(dir, DEC);
      }
         
      if (dir != diraktuell) beschleunigen(1, diraktuell);
     
      if (speedaktuell != speedon) beschleunigen(speedon, dir);
     
      motorGo(dir, speedon);
     
      if (analogRead(cspin[0]) > CS_THRESHOLD)        
      {
        motorOff();
      }
     
  }
       
}
// **************************************************************

void beschleunigen(int endspeed, int dirx)
{
  // Beschleunigen des Motors auf “speedon”
  if (endspeed != 0)
  {
      if (endspeed > speedaktuell)  // Wenn die neue Geschwindigkeit größer ist, dann beschleunigen
      {
     
        Serial.println(“beschleunigen”);

        i = speedaktuell;
       
        while(i<endspeed)
        {
          motorGo(dirx, i);   // Den Motorspeed immer um 1/255 erhöhen     
          delay(50);                        
          i++;
                                  
          if (analogRead(cspin[0]) > CS_THRESHOLD) // Ist der Motor blockiert und der Strom wird zuhoch, abschalten.
          {
            motorOff();
          }
         
          digitalWrite(statpin, LOW);
     
        }
      }

      if (endspeed < speedaktuell)  // Wenn die neue Geschwindigkeit kleiner ist, dann entschleunigen
      {
     
        i = speedaktuell;
       
        Serial.println(“entschleunigen”);
       
        while(i>endspeed)
        {
          motorGo(dirx, i);   // Den Motorspeed immer um 1/255 erhöhen     
          delay(50);                        
          i–;
                                  
          if (analogRead(cspin[0]) > CS_THRESHOLD) // Ist der Motor blockiert und der Strom wird zuhoch, abschalten.
          {
            motorOff();
          }
         
          digitalWrite(statpin, LOW);
     
        }
      }
      Serial.println(“Speed erreicht”);
      diraktuell = dir;
      speedaktuell = endspeed;
      i=1;
  }
}

void motorOff()
{

  for (int i=0; i<2; i++)
  {
    digitalWrite(inApin[i], LOW);
    digitalWrite(inBpin[i], LOW);
  }
 
  analogWrite(pwmpin[0], 0);
  analogWrite(pwmpin[1], 0);
 
  i=0;
 
  digitalWrite(13, HIGH);
 
  Serial.println(“Motor Locked”);
 
  delay(1000);
}

void motorGo(uint8_t direct, uint8_t pwm)
{
    if (direct <=4)
    {
      if (direct == 0) // Go forward
      {
        digitalWrite(inBpin[0], LOW);
        digitalWrite(inBpin[1], LOW);
        digitalWrite(inApin[0], HIGH);
        digitalWrite(inApin[1], HIGH);
      }
         
      if (direct == 1)  // Go backward
      {
        digitalWrite(inApin[0], LOW);
        digitalWrite(inApin[1], LOW);
        digitalWrite(inBpin[0], HIGH);
        digitalWrite(inBpin[1], HIGH);
      }
 
      if (direct == 2)  // Go left
      {
        digitalWrite(inApin[0], LOW);
        digitalWrite(inBpin[1], LOW);
        digitalWrite(inBpin[0], HIGH);
        digitalWrite(inApin[1], HIGH);
      }
     
      if (direct == 3)  // Go right
      {
        digitalWrite(inBpin[0], LOW);
        digitalWrite(inApin[1], LOW);
        digitalWrite(inApin[0], HIGH);
        digitalWrite(inBpin[1], HIGH);
      }
       
      analogWrite(pwmpin[0], pwm);
      analogWrite(pwmpin[1], pwm);
    }
}
[/code]

In diesem kleinen Post möchte ich mein Wissen zum bau eines kleinen GPS Moduls weitergeben. Ich musste selbe etwas aufwendiger suchen, um alle Informationen zu finden, die es mir dann recht schnell ermöglicht haben den GPS Receiver “HOLUX GM-210”, mit dem NMEA 0183 Protokoll,
 die für mich interessanten Daten zu entlocken.

Was für Materialien hab ich benutzt?

  • GPS Receiver HOLUX GM-210
  • LCD 1602 (Idealer Weise mit UT-LCDmenueSensor Board)Wir
  • ARDUINO Nano
Die Verdrahten des ARDUINOS mit dem GPS Receiver ist denkbar einfach, wenn man die richtigen Informationen hat. Wichtig ist es das man die TTL Datenanschlüsse (5V Signalpegel) benutzt und nicht die RS232 (12V Signalpegel) Anschlüsse.
 
 
 
 
 

Wir verbinden also den PIN2 vom GM-210 5V VDC mit den 5V Ausgang und den PIN4 Ground mit dem GND (Ground) am ARDUINO.

Jetzt noch den PIN3 Tx(TTL) mit einem Seriellen RxPin und den PIN5 Rx(TTL) mit dem TxPIN an dem ARDUINO.

So einfach ist die Hardware installiert.

Jetzt kommen wir zu der etwas größeren Aufgabe. Das Auslesen der Daten die uns das GPS sendet, und dann natürlich das Auswerten der Daten.
Denn wir wollen ja wissen wo wir sind, wie schnell wir sind und in welche Richtung wir uns bewegen.

 

Es stehen natürlich noch einige Daten mehr zu der Verfügung, aber die kann sich dann nach dem gleichen Prinzip jeder so anpassen wie er es gerne hätte.

Die Erklärung hab ich noch nicht ganz fertig, aber hier schon mal der Code:

*************************************************************

 #include <string.h>
 #include <ctype.h>

 #include <LiquidCrystal.h>
  // initialize the library with the numbers of the interface pins
  LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
 
 #include <SoftwareSerial.h>
  SoftwareSerial GPSserial(7, 6); // RX | TX

String inputString = “”;         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete

 void setup()
{

// initialize serial:
  Serial.begin(9600);
  GPSserial.begin(4800);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);

  lcd.begin(16, 2);
 
  lcd.print(“GPS Modul”);
  delay(2000);
 
}

 void loop()
 {
      serialEvent(); // Zeile einlesen
     
  // print the string when a newline arrives:
  if (stringComplete)
    {
      Serial.println(inputString);

      // you can also look for a substring in the middle of a string:
      // Ausgabe auf dem LCD
      if (inputString.substring(1,6) == “GPRMC”)
        {
          Serial.println(“Yes”);
          String ausgabe = (inputString.substring(20, 29));
         
          lcd.clear();
         
          lcd.setCursor(0, 0);
          lcd.print(“L:”);
          lcd.setCursor(0, 1);
          lcd.print(“B:”);
         
          lcd.setCursor(3, 0);
          lcd.print(ausgabe);
          ausgabe = “”;
          ausgabe = (inputString.substring(30, 31));
          lcd.setCursor(12, 0);
          lcd.print(ausgabe);
          ausgabe = “”;
          ausgabe = (inputString.substring(32, 42));
          lcd.setCursor(3, 1);
          lcd.print(ausgabe);
          ausgabe = “”;
          ausgabe = (inputString.substring(43, 44));
          lcd.setCursor(13, 1);
          lcd.print(ausgabe);
          ausgabe = “”;
         
          delay(1000);
         
          int kommaS = inputString.indexOf(‘,’, 46);
          ausgabe = (inputString.substring(45, kommaS – 1));
          float kmh = ausgabe.toFloat();
          kmh = kmh*1.852;

          lcd.clear();
         
          lcd.setCursor(0, 0);
          lcd.print(“S:”);
          lcd.setCursor(0, 1);
          lcd.print(“W:”);
 
          lcd.setCursor(3, 0);
          lcd.print(kmh, 6);
          ausgabe = “”;
          int kommaW = inputString.indexOf(‘,’, kommaS + 1);
          ausgabe = (inputString.substring(kommaS + 1, kommaW));
          lcd.setCursor(3, 1);
          lcd.print(ausgabe);
          ausgabe = “”;
          delay(1000);
        }
     
      // clear the string:
      inputString = “”;
      stringComplete = false;
    }
 }

 void serialEvent() {
  while (GPSserial.available())
    {
    // get the new byte:
    char inChar = (char)GPSserial.read();
   
    // add it to the inputString:
    inputString += inChar;
   
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == ‘n’)
      {
        stringComplete = true;
      }
  }
}

 

 

Wie mein kleiner Laser-Plotter entstanden ist

Das Thema Laserplotter scheint im Internet und unter den E-Bastlern sehr verbreitet zu sein. Was mich aber nicht wunder, da es mich auch schnell gepackt hat und ich dem Fieber verfallen bin.

Also machte ich mich als erstes auf die Suche nach Informationen über Laser und über Schrittmotoren.

Was nicht ganz einfach war. Es gibt zwar viel im Netz, aber entweder ist es für Menschen die sich schon ausreichend mit der Technik auskennen geschrieben, oder mit nur sehr wenigen Informationen zu den Details.

 

 

Was ich hier versuchen möchte ist viele nützliche Informationen zusammen zu tragen und zu verlinken.

 

Der ARDUINO mit dem AFmotor Shield (L293D), 2 Stepper und ein Servo läuft ganz gut mit der Firmeware GcodeCNCdemo und zum senden der Daten (GCODE) teste ich gerade GcodeSender, auch von MarginallyClever.
 

 

 
 

 

 

Ausschneiden aus Kunststoff 

 
 
 

Da es immer noch Probleme mit der Einstellung von Stepps pro Millimeter gibt, muss eine neue Steuerung her.

 
Jetzt mit einem easyDriver Set und der GRBL Software. 

 

 

 

 

 

 

 

 

 

 

Für die nächste Ausbaustufe habe ich schon mal Material bestellt bei: www.alu-Profil-Technik.de
Superservice und gute Preise.

 

 

 

 

 
 

 

 

 
 
 
 
 
 
 
 

 

 

 

Informationen zum HC-SR04 (Robosoftsystem)

************************************************************************************
Start Quellcode
************************************************************************************
// Prozesortaktfrequent festlegen
#define F_CPU 16000000UL

// Baudrate
#define BAUD 19200UL

// Baudratenberechnung
#define UBRR_VAL ((F_CPU+BAUD*8) / (BAUD*16)-1)

// CR ist Zeilenumbruch
#define CR 0x0D

// Benötigte Bibliotheken hinzufügen
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>

// Variablen deklarieren
uint16_t rising, falling;     // Zum speichern der Timerwerte bei steigender und fallender Flanke
int counts;                         // Die Differenz der beiden Timerwerte (Signallänge in TimerTakten)
float dist;                          // Der berechnete Abstand in cm mit bis zu 6 Kommastellen
uint16_t us_per_count;    // Die Länge eines TimerTaktes in us

// ********************************************************************************************************************************************
// ****************************************************** Serielle Übertragung ****************************************************************
// UART-Init ATmega328P

void uart_init(void)
{
    // Baudrate einstellen
    UBRR0H = (unsigned char)(UBRR_VAL>>8);
    UBRR0L = (unsigned char)UBRR_VAL;
   
    // Receiver und Transmitter einschalten
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
   
    // Frame Format: Asynchron 8N1
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
}

// Charakter schreiben (Ein Zeichen senden als ASCII)
void uart_putChar(unsigned char c)
{
    // Warten bis Sendepuffer leer ist
    while (!(UCSR0A & (1<<UDRE0)));
   
    // Daten in den Puffer schreiben und senden
    UDR0 = c;
}

// String senden (Einen Zeichenfolge in einzelne Zeichen zerlegen und an uart_putChar zum senden übergeben)
void uart_putStr(unsigned char *s)
{
    while (*s)
    {  
        // so lange *s != ‘�’ also ungleich dem “String-Endezeichen(Terminator)”
        uart_putChar(*s);
        s++;
    }
}
// ********************************************************************************************************************************************

// ********************************************************************************************************************************************
// ************************************************* ISP **************************************************************************************

// Int. wenn die sich verändernde Flanke (von “1 nach 0 – fallende” oder von “0 nach 1 – steigende”) erkannt wird. (An PIN PB0 (ARDUINO PIN 8))
ISR(TIMER1_CAPT_vect)
{
    if (TCCR1B & (1<<ICES1))     // (Wenn das Bit ICES1 im register TCCR1B = 1 ist, also einen steigende Flanke erkennt)
    {
        TCCR1B &= ~(1<<ICES1);     // (Erkennung umschalten auf fallende Flanke (Bit ICES1 im register TCCR1B = 0))
        rising = ICR1;                           // (Den beim auslösen des Int. im Register ICR1 gespeicherten Timer/Counter Wert in die Variable “rising” speichern)

    }
    else // (Wenn das Bit ICES1 im register TCCR1B = 0 ist, also einen fallende Flanke erkennt)
    {
        TCCR1B |= (1<<ICES1);     // (Erkennung umschalten auf steigende Flanke (Bit ICES1 im register TCCR1B = 1))
        falling = ICR1;                      // (Den beim auslösen des Int. im Register ICR1 gespeicherten Timer/Counter Wert in die Variable “falling” speichern)
        counts = falling – rising;        // die Differenz zwischen tEnd und tStart berechnen (z.B.: Steigende Flanke erkannt bei tStart=120, fallenden Flanke erkannt bei tEnd=670 – 670-120=tPuls=550)

        dist = (float)us_per_count * counts * 10 / 580;     // (Laufzeit Schall in Weg “cm” umrechnen)
    }
}

// Is triggered on timer match of OCR1A (Int. wenn der Vergleichswert in OCR1A erreicht ist)
ISR(TIMER1_COMPA_vect)
{
    // Generate a 12us pulse to trigger the HR-SR04
    PORTB ^= (1<<PIN2);
    _delay_us(12);
    PORTB ^= (1<<PIN2);
}
// ********************************************************************************************************************************************

int main(void)
{
    // Uart Init
    uart_init();
   
    unsigned char str[10];
   
    DDRB |= (1<<PIN2);      // PORTB PIN 2 as output
    DDRB |= (1<<PIN5);      // PORTB PIN 5 as output
   
   
   
    // ********************************************************************************************************************************************
    // *************************************************************** TIMER1 INIT ****************************************************************

    TCCR1B |= (1<<ICNC1) | (1<<CS10) | (1<<CS11) | (1<<WGM12);      //ICNC1:Rauschunterdrückung, CS10 and CS11: Prescale (Teiler) auf 64, WGM12: CTC-Modus auswählen
    TIMSK1 |= (1<<ICIE1) | (1<<OCIE1A);      // Int. auslösen bei: Erreichen von TOP, bei steigender bzw. fallender Flanke
    TCCR1B |= (1<<ICES1);      // Int. auslösen bei steigender Flanke
   
    // TOP berechnen (70ms Laufzeit für einene Cyclus): 16MHz/64 = 250000count/sek = 250000/1000 = 25000count/us / 100 * 70 = 17500 count/70ms

    OCR1A = 17500;

      
    // CPU-Takt / Prescale = Takte/Sek. 1Sek / Takt/Sek = 4 ( t = 4us/Takt)
    us_per_count = 4;

    sei();     //Interrupt global aktivieren

    // Endlosschleife
    while (1)
    {
        if (dist < 300)     // Wenn die Distanz innerhalb des Messbereiches (max. 300cm) liegt, …
        {
            uart_putStr(dtostrf(dist, 1, 2, str));     // … dann Ausgabe der Distanz mit 2 Stellen hinter dem Komma per Seriell
            uart_putStr(” cm”);      // schreibe hinter dem Wert ein “cm”
            uart_putStr(“r”);     // gehe zurück zum Anfang der Zeile
        }
        else     // Wenn nicht, …
        {
            uart_putStr(“ERROR”);     // … schreibe “ERROR” in dei Ausgabe
            uart_putStr(“r”);    
// gehe zurück zum Anfang der Zeile 
        }
       
       
        _delay_ms(250);
    }
}


**********************************************************************************
Ende Quellcode
**********************************************************************************

Diese Seiten habne mir geholfen das Projekt umzusetzen:

ATmega168/328-Arduino Pin Mapping
CONVERTWORLD.COM – Umrechnen von Einheiten ganz einfach

 

Vielen Dank!