Ich bin gerade etwas geflasht von conda (https://conda.io). Meine Lieblingssprache ist python und als Pythonentwickler hat man neben dem ewigen Python2 vs. Python3-Syntaxproblem auch immer noch das Problem, dass bestimmte Pakete (möglicherweise sogar in unterschiedlichen Versionen) in unterschiedlichen Projekten benötigt werden. Das ganze kann man jetzt mit natürlich auch über Virtualisierung lösen, aber das ist einigermaßen umständlich und ressourcenfressend, finde ich.

conda geht da einen etwas stringenteren Ansatz. Es schafft einen Ansatz aus eigenen Umgebungen (“environments”), die sich selber in der klassischen create, modifiy, delete-Idee verwalten lassen. Zusätzlich bietet conda die Funktion, Umgebungen zu exportieren und importieren, also wie man im Neuland sagt – zu teilen.

Innerhalb von conda befindet sich eine komplette Paketverwaltung, man kann also conda anstelle von pip verwenden, wobei conda die Pakete jeweils nur in die gerade aktive Umgebung installiert.

Wozu braucht man das?

Eine klassische Anwendung für conda sehe ich im Bereich Softwaretests in verschiedenen Umgebungen.

  • Läuft die Software auch in python3?
  • Wenn ich auf paketxy-0.0.5 bekomme ich dann deprecated-Meldungen?

Zudem ist es leichter, zwischen Entwicklern die gleiche Umgebung zu schaffen, um überhaupt valide Tests durchführen zu können. Außerdem schafft conda die Möglichkeit, eine Umgebung, die man vielleicht für einen Bugfix für eine fremde Software benötigt, nur temporär auf dem eigenen System zu halten, um es nicht zusätzlich zuzumüllen.

Ich will hier auch nicht den Eindruck aufkommen lassen, conda sei nur für python gedacht. Nein! Es kann sowohl Paketverwaltung für viele Sprachen mehr sein und läuft auch unter den drei wichtigen Betriebsystemen als Umgebungsverwaltung.

Wie sieht es aus?

Es gibt zahlreiche Videos zur Verwendung von conda. Mir hat dieses hier besonders gefallen, weil es die verschiedenen Möglichkeiten von conda nett zusammenfasst. Nicht über das lange Intro wundern. Der Sprecher erzählt erst einiges über den Einsatz von anaconda, als dem darüberliegenden Framework, welches conda enthält.

ESP-WROOM-32

Hallo zusammen,

hier eine gute Anleitung auf deutsch, wie Ihr das MicroPhython auf dem ESP installiert und die ersten Gehversuche macht.

Ein ESP32 mit MicroPython (Video – YouTube)

Hier noch die wichtigsten Links:

https://micropython.org/download#esp32

Python 3.x.x für OS?

Hier die schnelle Übersicht zu ganz einfachen Befehlen …

Welcome to MicroPython on the ESP32!

For generic online docs please visit http://docs.micropython.org/


https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki


For access to the hardware use the ‘machine’ module:

import machine                // besser: from machine import Pin (spart Speicher)

pin12 = machine.Pin(12, machine.Pin.OUT)

pin12.value(1)

pin13 = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)

print(pin13.value())

i2c = machine.I2C(scl=machine.Pin(21), sda=machine.Pin(22))

i2c.scan()

i2c.writeto(addr, b'1234')

i2c.readfrom(addr, 4)

 

Basic WiFi configuration:

import network

sta_if = network.WLAN(network.STA_IF); sta_if.active(True)

sta_if.scan()                             # Scan for available access points

sta_if.connect("<AP_name>", "<password>") # Connect to an AP

sta_if.isconnected()                      # Check for successful connection

 

Control commands:

  CTRL-A        -- on a blank line, enter raw REPL mode

  CTRL-B        -- on a blank line, enter normal REPL mode

  CTRL-C        -- interrupt a running program

  CTRL-D        -- on a blank line, do a soft reset of the board

  CTRL-E        -- on a blank line, enter paste mode

For further help on a specific object, type help(obj)

For a list of available modules, type help(‘modules’)

—————————————————————————

MicroPython

Shell:

screen /dev/tty.ESPPORT 115200           // Shell starten und mit dem ESP verbinden default:115200 dann 2-3 mal "CTRL + C" drücken ...

>>>Befehl

Beispiel:

>>>print("Hallo")

——————————————————————————————

noch etwas netter ist die RShell

Aufrufen mit:

rshell --buffer-ssize=30 -p /dev/tty.ESPPORT         //(bei mir z.B.: /dev/tty.SLAB_USBtoUART)

Befehle in der RSHELL:

boards                       // zeigt Dir alle angeschlossenen Boards und die Namen

ls "boardname"          // z.B.: "ls pyboard" - listet die Dateien auf dem Board. Wenn Ihr noch //nichts gemacht habt dann findet Ihr da nur die boot.py 

                                // Die boot.py wird bei jedem Start des Boards ausgeführt. Auch nach dem aufwachen aus dem DeepSleep Modus.

                                // Euer Programm steht dann in der Regel in der main.py

edit /pyboard/boot.py            // ruft die Datei boot.py im StandartEditor auf. Exit mit :q! für nicht speichern

Etwas netter ist es wenn Ihr einen anderen Editor benutzt. Verlasst die rshell und startet sie neu mit dem Befehl:

rshell --buffer-size=30 -p /dev/tty.ESPPORT -a -e nano

// damit macht Ihr für die aktuelle Sitzung den Editor "nano" zum StandartEditor

——————————————————————————————–

Aufrufen einer KomandoOberfläche (REPL):

REPL                              // hier könnt Ihr wieder direkt Befehle ausführen

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