Merge remote-tracking branch 'origin/release' into feature/#20-communication

This commit is contained in:
Anton Jacker
2024-06-13 13:10:56 +02:00
34 changed files with 86976 additions and 93 deletions

View File

@@ -1,23 +1,22 @@
//
// Created by Anton Jacker on 24.11.23.
//
#define SDA_PIN 1
#define SCL_PIN 2
#include "Dezibot.h"
#include <SPI.h>
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#define GPIO_LED 48
void Dezibot::begin(void) {
Wire.begin(SDA_PIN,SCL_PIN);
infraredLight.begin();
lightDetection.begin();
motion.begin();
lightDetection.begin();
colorDetection.begin();
multiColorLight.begin();
motionDetection.begin();
infraredLight.begin();
}
display.begin();
};

View File

@@ -1,6 +1,6 @@
/**
* @file Dezibot.h
* @author your name (you@domain.com)
* @author Hans Haupt, Jens Wagner, Anina Morgner, Anton Jacker, Saskia Dübener
* @brief
* @version 0.1
* @date 2023-11-19
@@ -18,6 +18,7 @@
#include "motionDetection/MotionDetection.h"
#include "infraredLight/InfraredLight.h"
#include "communication/Communication.h"
#include "display/Display.h"
class Dezibot {
@@ -31,23 +32,8 @@ public:
MotionDetection motionDetection;
InfraredLight infraredLight;
Communication communication;
Display display;
void begin(void);
/*
Display display
IRCommuncation irCommuncation (beinhaltet Kommuniaktion / Annhärung...)
Battery battery
Extension extension
WiFi wifi //wie wird WiFi geschrieben?
//nur lesender Zugriff, in dieser Klasse sind andere Instanzen mit dem Dezibotinterface gekapselt
Friends friends
OperatingSystem operatingSystem
USBCommunication usbCommunication
Button button
//nicht unique, initzial Dezibot
String robotName
*/
};
#endif //Dezibot_h

View File

@@ -1,7 +1,6 @@
#include "ColorDetection.h"
void ColorDetection::begin(void){
Wire.begin(I2C_MASTER_SDA_IO,I2C_MASTER_SCL_IO);
ColorDetection::configure(VEML_CONFIG{.mode = AUTO,.enabled = true,.exposureTime=MS40});
};
void ColorDetection::configure(VEML_CONFIG config){

View File

@@ -1,3 +1,14 @@
/**
* @file ColorDetecion.h
* @author Hans Haupt
* @brief Class that controls the colorsensor (VEML6040) of the dezibot.
* @version 0.1
* @date 2024-06-01
*
* @copyright Copyright (c) 2024
*
*/
#ifndef ColorDetection_h
#define ColorDetection_h
#include <stdint.h>

147
src/display/CharTable.h Normal file
View File

@@ -0,0 +1,147 @@
/**
* @file CharTable.h
* @author Hans Haupt (hans.haupt@dezibot.de)
* @brief LookUpTable for 8x8 Pixel Characters for an SSD1306 Display
* @version 0.1
* @date 2024-05-24
*
* @copyright Copyright (c) 2024
*
*/
/**
* @brief First index specifies the index, where index equals the ascii encoding
* unprintable characters are encode as all zero
* the first byte in an entry is the cmd_byte for SSD1306 and therefore not printed
* Encoding is colum wise, so first byte is the first column of the char and so on
*
*/
const char font8x8_colwise[128][9] = {{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+0()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+1()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+2()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+3()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+4()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+5()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+6()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+7()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+8()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+9()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+a()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+b()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+c()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+d()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+e()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+f()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+10()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+11()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+12()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+13()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+14()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+15()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+16()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+17()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+18()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+19()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+1a()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+1b()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+1c()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+1d()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+1e()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+1f()
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // U+20( )
{ 0x40,0x00,0x00,0x06,0x5f,0x5f,0x06,0x00,0x00}, // U+21(!)
{ 0x40,0x00,0x03,0x03,0x00,0x03,0x03,0x00,0x00}, // U+22(")
{ 0x40,0x14,0x7f,0x7f,0x14,0x7f,0x7f,0x14,0x00}, // U+23(#)
{ 0x40,0x24,0x2e,0x6b,0x6b,0x3a,0x12,0x00,0x00}, // U+24($)
{ 0x40,0x46,0x66,0x30,0x18,0x0c,0x66,0x62,0x00}, // U+25(%)
{ 0x40,0x30,0x7a,0x4f,0x5d,0x37,0x7a,0x48,0x00}, // U+26(&)
{ 0x40,0x04,0x07,0x03,0x00,0x00,0x00,0x00,0x00}, // U+27(')
{ 0x40,0x00,0x1c,0x3e,0x63,0x41,0x00,0x00,0x00}, // U+28(()
{ 0x40,0x00,0x41,0x63,0x3e,0x1c,0x00,0x00,0x00}, // U+29())
{ 0x40,0x08,0x2a,0x3e,0x1c,0x1c,0x3e,0x2a,0x08}, // U+2a(*)
{ 0x40,0x08,0x08,0x3e,0x3e,0x08,0x08,0x00,0x00}, // U+2b(+)
{ 0x40,0x00,0x80,0xe0,0x60,0x00,0x00,0x00,0x00}, // U+2c(,)
{ 0x40,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00}, // U+2d(-)
{ 0x40,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00}, // U+2e(.)
{ 0x40,0x60,0x30,0x18,0x0c,0x06,0x03,0x01,0x00}, // U+2f(/)
{ 0x40,0x3e,0x7f,0x71,0x59,0x4d,0x7f,0x3e,0x00}, // U+30(0)
{ 0x40,0x40,0x42,0x7f,0x7f,0x40,0x40,0x00,0x00}, // U+31(1)
{ 0x40,0x62,0x73,0x59,0x49,0x6f,0x66,0x00,0x00}, // U+32(2)
{ 0x40,0x22,0x63,0x49,0x49,0x7f,0x36,0x00,0x00}, // U+33(3)
{ 0x40,0x18,0x1c,0x16,0x53,0x7f,0x7f,0x50,0x00}, // U+34(4)
{ 0x40,0x27,0x67,0x45,0x45,0x7d,0x39,0x00,0x00}, // U+35(5)
{ 0x40,0x3c,0x7e,0x4b,0x49,0x79,0x30,0x00,0x00}, // U+36(6)
{ 0x40,0x03,0x03,0x71,0x79,0x0f,0x07,0x00,0x00}, // U+37(7)
{ 0x40,0x36,0x7f,0x49,0x49,0x7f,0x36,0x00,0x00}, // U+38(8)
{ 0x40,0x06,0x4f,0x49,0x69,0x3f,0x1e,0x00,0x00}, // U+39(9)
{ 0x40,0x00,0x00,0x66,0x66,0x00,0x00,0x00,0x00}, // U+3a(:)
{ 0x40,0x00,0x80,0xe6,0x66,0x00,0x00,0x00,0x00}, // U+3b(;)
{ 0x40,0x08,0x1c,0x36,0x63,0x41,0x00,0x00,0x00}, // U+3c(<)
{ 0x40,0x24,0x24,0x24,0x24,0x24,0x24,0x00,0x00}, // U+3d(=)
{ 0x40,0x00,0x41,0x63,0x36,0x1c,0x08,0x00,0x00}, // U+3e(>)
{ 0x40,0x02,0x03,0x51,0x59,0x0f,0x06,0x00,0x00}, // U+3f(?)
{ 0x40,0x3e,0x7f,0x41,0x5d,0x5d,0x1f,0x1e,0x00}, // U+40(@)
{ 0x40,0x7c,0x7e,0x13,0x13,0x7e,0x7c,0x00,0x00}, // U+41(A)
{ 0x40,0x41,0x7f,0x7f,0x49,0x49,0x7f,0x36,0x00}, // U+42(B)
{ 0x40,0x1c,0x3e,0x63,0x41,0x41,0x63,0x22,0x00}, // U+43(C)
{ 0x40,0x41,0x7f,0x7f,0x41,0x63,0x3e,0x1c,0x00}, // U+44(D)
{ 0x40,0x41,0x7f,0x7f,0x49,0x5d,0x41,0x63,0x00}, // U+45(E)
{ 0x40,0x41,0x7f,0x7f,0x49,0x1d,0x01,0x03,0x00}, // U+46(F)
{ 0x40,0x1c,0x3e,0x63,0x41,0x51,0x73,0x72,0x00}, // U+47(G)
{ 0x40,0x7f,0x7f,0x08,0x08,0x7f,0x7f,0x00,0x00}, // U+48(H)
{ 0x40,0x00,0x41,0x7f,0x7f,0x41,0x00,0x00,0x00}, // U+49(I)
{ 0x40,0x30,0x70,0x40,0x41,0x7f,0x3f,0x01,0x00}, // U+4a(J)
{ 0x40,0x41,0x7f,0x7f,0x08,0x1c,0x77,0x63,0x00}, // U+4b(K)
{ 0x40,0x41,0x7f,0x7f,0x41,0x40,0x60,0x70,0x00}, // U+4c(L)
{ 0x40,0x7f,0x7f,0x0e,0x1c,0x0e,0x7f,0x7f,0x00}, // U+4d(M)
{ 0x40,0x7f,0x7f,0x06,0x0c,0x18,0x7f,0x7f,0x00}, // U+4e(N)
{ 0x40,0x1c,0x3e,0x63,0x41,0x63,0x3e,0x1c,0x00}, // U+4f(O)
{ 0x40,0x41,0x7f,0x7f,0x49,0x09,0x0f,0x06,0x00}, // U+50(P)
{ 0x40,0x1e,0x3f,0x21,0x71,0x7f,0x5e,0x00,0x00}, // U+51(Q)
{ 0x40,0x41,0x7f,0x7f,0x09,0x19,0x7f,0x66,0x00}, // U+52(R)
{ 0x40,0x26,0x6f,0x4d,0x59,0x73,0x32,0x00,0x00}, // U+53(S)
{ 0x40,0x03,0x41,0x7f,0x7f,0x41,0x03,0x00,0x00}, // U+54(T)
{ 0x40,0x7f,0x7f,0x40,0x40,0x7f,0x7f,0x00,0x00}, // U+55(U)
{ 0x40,0x1f,0x3f,0x60,0x60,0x3f,0x1f,0x00,0x00}, // U+56(V)
{ 0x40,0x7f,0x7f,0x30,0x18,0x30,0x7f,0x7f,0x00}, // U+57(W)
{ 0x40,0x43,0x67,0x3c,0x18,0x3c,0x67,0x43,0x00}, // U+58(X)
{ 0x40,0x07,0x4f,0x78,0x78,0x4f,0x07,0x00,0x00}, // U+59(Y)
{ 0x40,0x47,0x63,0x71,0x59,0x4d,0x67,0x73,0x00}, // U+5a(Z)
{ 0x40,0x00,0x7f,0x7f,0x41,0x41,0x00,0x00,0x00}, // U+5b([)
{ 0x40,0x01,0x03,0x06,0x0c,0x18,0x30,0x60,0x00}, // U+5c(\)
{ 0x40,0x00,0x41,0x41,0x7f,0x7f,0x00,0x00,0x00}, // U+5d(])
{ 0x40,0x08,0x0c,0x06,0x03,0x06,0x0c,0x08,0x00}, // U+5e(^)
{ 0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80}, // U+5f(_)
{ 0x40,0x00,0x00,0x03,0x07,0x04,0x00,0x00,0x00}, // U+60(`)
{ 0x40,0x20,0x74,0x54,0x54,0x3c,0x78,0x40,0x00}, // U+61(a)
{ 0x40,0x41,0x7f,0x3f,0x48,0x48,0x78,0x30,0x00}, // U+62(b)
{ 0x40,0x38,0x7c,0x44,0x44,0x6c,0x28,0x00,0x00}, // U+63(c)
{ 0x40,0x30,0x78,0x48,0x49,0x3f,0x7f,0x40,0x00}, // U+64(d)
{ 0x40,0x38,0x7c,0x54,0x54,0x5c,0x18,0x00,0x00}, // U+65(e)
{ 0x40,0x48,0x7e,0x7f,0x49,0x03,0x02,0x00,0x00}, // U+66(f)
{ 0x40,0x98,0xbc,0xa4,0xa4,0xf8,0x7c,0x04,0x00}, // U+67(g)
{ 0x40,0x41,0x7f,0x7f,0x08,0x04,0x7c,0x78,0x00}, // U+68(h)
{ 0x40,0x00,0x44,0x7d,0x7d,0x40,0x00,0x00,0x00}, // U+69(i)
{ 0x40,0x60,0xe0,0x80,0x80,0xfd,0x7d,0x00,0x00}, // U+6a(j)
{ 0x40,0x41,0x7f,0x7f,0x10,0x38,0x6c,0x44,0x00}, // U+6b(k)
{ 0x40,0x00,0x41,0x7f,0x7f,0x40,0x00,0x00,0x00}, // U+6c(l)
{ 0x40,0x7c,0x7c,0x18,0x38,0x1c,0x7c,0x78,0x00}, // U+6d(m)
{ 0x40,0x7c,0x7c,0x04,0x04,0x7c,0x78,0x00,0x00}, // U+6e(n)
{ 0x40,0x38,0x7c,0x44,0x44,0x7c,0x38,0x00,0x00}, // U+6f(o)
{ 0x40,0x84,0xfc,0xf8,0xa4,0x24,0x3c,0x18,0x00}, // U+70(p)
{ 0x40,0x18,0x3c,0x24,0xa4,0xf8,0xfc,0x84,0x00}, // U+71(q)
{ 0x40,0x44,0x7c,0x78,0x4c,0x04,0x1c,0x18,0x00}, // U+72(r)
{ 0x40,0x48,0x5c,0x54,0x54,0x74,0x24,0x00,0x00}, // U+73(s)
{ 0x40,0x00,0x04,0x3e,0x7f,0x44,0x24,0x00,0x00}, // U+74(t)
{ 0x40,0x3c,0x7c,0x40,0x40,0x3c,0x7c,0x40,0x00}, // U+75(u)
{ 0x40,0x1c,0x3c,0x60,0x60,0x3c,0x1c,0x00,0x00}, // U+76(v)
{ 0x40,0x3c,0x7c,0x70,0x38,0x70,0x7c,0x3c,0x00}, // U+77(w)
{ 0x40,0x44,0x6c,0x38,0x10,0x38,0x6c,0x44,0x00}, // U+78(x)
{ 0x40,0x9c,0xbc,0xa0,0xa0,0xfc,0x7c,0x00,0x00}, // U+79(y)
{ 0x40,0x4c,0x64,0x74,0x5c,0x4c,0x64,0x00,0x00}, // U+7a(z)
{ 0x40,0x08,0x08,0x3e,0x77,0x41,0x41,0x00,0x00}, // U+7b({)
{ 0x40,0x00,0x00,0x00,0x77,0x77,0x00,0x00,0x00}, // U+7c(|)
{ 0x40,0x41,0x41,0x77,0x3e,0x08,0x08,0x00,0x00}, // U+7d(})
{ 0x40,0x02,0x03,0x01,0x03,0x02,0x03,0x01,0x00}, // U+7e(~)
{ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}; // U+7f(°)

138
src/display/Display.cpp Normal file
View File

@@ -0,0 +1,138 @@
/**
* @file Display.cpp
* @author Hans Haupt (hans.haupt@dezibot.de)
* @brief Adds the ability to print to the display of the robot.
* @version 0.1
* @date 2024-06-05
*
* @copyright Copyright (c) 2024
*/
#include "Display.h"
#include "CharTable.h"
#include "Wire.h"
void Display::begin(void){
//set Mux Ratio
sendDisplayCMD(muxRatio);
sendDisplayCMD(0x3f);
sendDisplayCMD(setOffset);
sendDisplayCMD(0x00);
sendDisplayCMD(setStartLine);
sendDisplayCMD(stopCompleteOn);
/*which pixels are bright: normal = 1s are bright, inverese= 0s are bright*/
sendDisplayCMD( setNormalMode);
sendDisplayCMD( setOscFreq);
sendDisplayCMD(0x80);
sendDisplayCMD(setChargePump);
sendDisplayCMD(0x14);
sendDisplayCMD(activateDisplay);
this->clear();
return;
};
void Display::sendDisplayCMD(uint8_t cmd){
Wire.beginTransmission(DisplayAdress);
Wire.write(cmd_byte);
Wire.write(cmd);
Wire.endTransmission();
};
void Display::clear(void){
sendDisplayCMD(addressingMode);
sendDisplayCMD(0x00); //horizontal
sendDisplayCMD(colRange);
sendDisplayCMD(0x00);
sendDisplayCMD(0x7f);
sendDisplayCMD(pageRange);
sendDisplayCMD(0x00);
sendDisplayCMD(0x07);
for (int j=0;j<64;j++){
Wire.beginTransmission(DisplayAdress);
Wire.write(data_byte);
for(int i = 0;i<16;i++){
Wire.write(0x00);
}
Wire.endTransmission();
}
this -> charsOnCurrLine = 0;
this -> currLine = 0;
return;
};
void Display::updateLine(uint charAmount)
{
if(charAmount+this->charsOnCurrLine>16)
{
this->currLine = (this->currLine+((charAmount+this->charsOnCurrLine)/16))%8;
this->charsOnCurrLine = (charAmount+this->charsOnCurrLine)%17; //there can be 0-16 chars on one line, so the 17th char is on next line
}
else
{
this->charsOnCurrLine = charAmount+this->charsOnCurrLine;
}
};
void Display::print(char *value){
char *nextchar;
/* write data to the buffer */
while(value && *value != '\0') //check if pointer is still valid and string is not terminated
{
//check if next character is a linebreak
if(*value=='\n')
{
//fill the current line with blanks
while(this->charsOnCurrLine<16)
{
updateLine(1);
Wire.beginTransmission(DisplayAdress);
for(int i = 0;i<9;i++){
Wire.write(font8x8_colwise[0][i]);
}
Wire.endTransmission();
}
//make the linebreak
this->currLine=currLine+1;
this->charsOnCurrLine=0;
}
else
{
updateLine(1);
Wire.beginTransmission(DisplayAdress);
//print the character
for(int i = 0;i<9;i++){
Wire.write(font8x8_colwise[*value][i]);
}
Wire.endTransmission();
}
value++;
}
};
void Display::println(char *value){
this ->print(value);
this->print("\n");
};
void Display::flipOrientation(void){
if(this->orientationFlipped){
sendDisplayCMD(setComDirectionNormal);
sendDisplayCMD(setSegmentMap);
} else{
sendDisplayCMD(setComDirectionFlipped);
sendDisplayCMD(setSegmentReMap);
}
this->orientationFlipped = !this->orientationFlipped;
};
void Display::invertColor(void){
if(this->colorInverted){
sendDisplayCMD(setNormalMode);
} else {
sendDisplayCMD(setInverseMode);
}
this->colorInverted = !this->colorInverted;
};

89
src/display/Display.h Normal file
View File

@@ -0,0 +1,89 @@
/**
* @file InfraredLight.h
* @author Hans Haupt (hans.haupt@dezibot.de)
* @brief Adds the ability to print to the display of the robot.
* @version 0.1
* @date 2024-05-24
*
* @copyright Copyright (c) 2024
*
*/
#ifndef Display_h
#define Display_h
#include <stdint.h>
#include <Arduino.h>
#include "DisplayCMDs.h"
class Display{
protected:
//how many chars are on current line
uint8_t charsOnCurrLine = 0;
//on which line are we currently printing
uint8_t currLine = 0;
//flag that marks if the y-orientation is currently flipped
bool orientationFlipped = false;
//flag thats marks if the color is currently inverted
bool colorInverted = false;
/**
* @brief sends the passed cmd to the display, cmd_byte is added as prefix by the function
*
* @param cmd the byte instruction that shold by sent
*/
void sendDisplayCMD(uint8_t cmd);
/**
* @brief should be called whenever characters where printed to the display.
* Updates the data of the class to handle linebreaks correctly
* @param charAmount How many characters where added to the screen
*/
void updateLine(uint charAmount);
public:
/**
* @brief initializes the display datastructures and sents the required cmds to start the display. Should only be called once.
* @warning doesn't initalize the I²C bus itself, therefore wire.begin(1,2) must be called elsewhere, before this method.
*/
void begin(void);
/**
* @brief delets all content from the display, resets the linecounter, new print will start at the top left.
* Orientationflip is not resetted
*/
void clear(void);
/**
* @brief prints the passed string right behind the current displaycontent
* the sequence "\n" can be used to make a linebreak on the display
*
* @param value the string "xyz" that should be printed to the display
*/
void print(char *value);
/**
* @brief same as the print method, but after the string a line break is inserted
*
* @param value the string that should be printed
*/
void println(char *value);
/**
* @brief flips the horizontal orientation of all content on the display
*/
void flipOrientation(void);
/**
* @brief inverts the pixelcolors, so pixels on will be set to off and currently off pixels will be turned off.
* affects already printed content as well as future prints.
*
*/
void invertColor(void);
};
#endif //Display_h

24
src/display/DisplayCMDs.h Normal file
View File

@@ -0,0 +1,24 @@
#define cmd_byte 0x80
#define data_byte 0x40
#define muxRatio 0xa8 //needs second argument ranging from 16-63
#define setOffset 0xd3 //needs second argument ranging from 0-63
#define setStartLine 0x40
#define setSegmentMap 0xa0
#define setSegmentReMap 0xa1
#define setComDirectionNormal 0xc0
#define setComDirectionFlipped 0xc8
#define setComHardwareConfig 0xda //needs second arg
#define setContrast 0x81 //needs second arg
#define completeOn 0xa5
#define stopCompleteOn 0xa4
#define setNormalMode 0xa6
#define setInverseMode 0xa7
#define setOscFreq 0xd5 //needs second arg
#define setChargePump 0x8d//needs second arg 0x14 for enable
#define activateDisplay 0xaf
#define disableDisplay 0xae
#define addressingMode 0x20
#define colRange 0x21
#define pageRange 0x22
#define DisplayAdress 0x3C

View File

@@ -1,9 +1,7 @@
#include "InfraredLight.h"
#define pwmSpeedMode LEDC_LOW_SPEED_MODE
#define fooPin 13
#define footimer LEDC_TIMER_0
#define foochannel LEDC_CHANNEL_0
InfraredLED::InfraredLED(uint8_t pin,ledc_timer_t timer, ledc_channel_t channel){
this->ledPin = pin;
this->timer = timer;
@@ -16,7 +14,7 @@ void InfraredLED::begin(void){
.speed_mode = pwmSpeedMode,
.duty_resolution = LEDC_TIMER_10_BIT,
.timer_num = this->timer,
.freq_hz = 1,
.freq_hz = 800,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&pwmTimer);

View File

@@ -14,10 +14,6 @@
#include <Arduino.h>
#include "driver/ledc.h"
enum IRLeds{
Bottom,
Front
};
class InfraredLED{
public:
@@ -26,7 +22,6 @@ class InfraredLED{
/**
* @brief enables selected LED
*
* @param led
*/
void turnOn(void);
/**

View File

@@ -1,4 +1,5 @@
#include "LightDetection.h"
#include <limits.h>
void LightDetection::begin(void){
LightDetection::beginInfrared();
@@ -6,7 +7,6 @@ void LightDetection::begin(void){
};
uint16_t LightDetection::getValue(photoTransistors sensor){
uint16_t result;
switch(sensor){
//Fall Through intended
case IR_FRONT:
@@ -17,6 +17,9 @@ uint16_t LightDetection::getValue(photoTransistors sensor){
case DL_BOTTOM:
case DL_FRONT:
return readDLPT(sensor);
default:
//currently not reachable, just if enum will be extended in the future
return UINT16_MAX;
}
};
@@ -26,6 +29,7 @@ photoTransistors LightDetection::getBrightest(ptType type){
uint16_t currentReading = 0;
if (type == IR){
maxSensor = IR_FRONT;
for(const auto pt : allIRPTs){
currentReading = LightDetection::getValue(pt);
if (currentReading > maxReading){
@@ -34,6 +38,7 @@ photoTransistors LightDetection::getBrightest(ptType type){
}
}
} else {
maxSensor = DL_FRONT;
for(const auto pt : allDLPTs){
currentReading = LightDetection::getValue(pt);
if (currentReading > maxReading){
@@ -47,6 +52,7 @@ photoTransistors LightDetection::getBrightest(ptType type){
};
uint32_t LightDetection::getAverageValue(photoTransistors sensor, uint32_t measurments, uint32_t timeBetween){
TickType_t xLastWakeTime = xTaskGetTickCount();
TickType_t frequency = timeBetween / portTICK_PERIOD_MS;
uint64_t cumulatedResult = 0;
@@ -58,6 +64,7 @@ uint32_t LightDetection::getAverageValue(photoTransistors sensor, uint32_t measu
};
void LightDetection::beginInfrared(void){
digitalWrite(IR_PT_ENABLE,true);
pinMode(IR_PT_ENABLE, OUTPUT);
pinMode(IR_PT_FRONT_ADC, INPUT);
pinMode(IR_PT_LEFT_ADC, INPUT);
@@ -66,13 +73,14 @@ void LightDetection::beginInfrared(void){
};
void LightDetection::beginDaylight(void){
digitalWrite(DL_PT_ENABLE,true);
pinMode(DL_PT_ENABLE, OUTPUT);
pinMode(DL_PT_BOTTOM_ADC, INPUT);
pinMode(DL_PT_FRONT_ADC, INPUT );
};
uint16_t LightDetection::readIRPT(photoTransistors sensor){
digitalWrite(IR_PT_ENABLE,HIGH);
//digitalWrite(IR_PT_ENABLE,HIGH);
uint16_t result = 0;
switch (sensor)
{
@@ -91,7 +99,7 @@ uint16_t LightDetection::readIRPT(photoTransistors sensor){
default:
break;
}
digitalWrite(IR_PT_ENABLE,LOW);
//digitalWrite(IR_PT_ENABLE,LOW);
return result;
};

View File

@@ -62,7 +62,7 @@ public:
* Can distingish between IR and Daylight
*
* @param type select which PTTransistors to compare
* @return photoTransistors which sensor is exposed to the greatest amount of light
* @return photoTransistors which sensor is exposed to the greatest amount of light, if all sensor read 0, the front sensor is returned
*/
static photoTransistors getBrightest(ptType type);
@@ -91,13 +91,7 @@ protected:
static void beginInfrared(void);
static void beginDaylight(void);
static uint16_t readIRPT(photoTransistors sensor);
static uint16_t readDLPT(photoTransistors sensor);
static void averageMeasurmentTask(void * args);
static uint16_t readDLPT(photoTransistors sensor);
};
#endif //LightDetection_h

View File

@@ -1,6 +1,6 @@
#include "MotionDetection.h"
MotionDetection::MotionDetection(){//:handler(FSPI){
MotionDetection::MotionDetection(){
handler = new SPIClass(FSPI);
};
@@ -9,13 +9,20 @@ void MotionDetection::begin(void){
digitalWrite(34,HIGH);
handler->begin(36,37,35,34);
handler->beginTransaction(SPISettings(frequency,SPI_MSBFIRST,SPI_MODE0));
digitalWrite(34,LOW);
// set Accel and Gyroscop to Low Noise
handler->transfer(PWR_MGMT0);
handler->transfer(0x1F);
handler->transfer(0x0F);
//busy Wait for startup
delayMicroseconds(200);
delayMicroseconds(250);
//set Gyroconfig
handler->transfer(0x20);
handler->transfer(0x25);
//set Gyro Filter
handler->transfer(0x23);
handler->transfer(0x37);
digitalWrite(34,HIGH);
handler->endTransaction();
};
@@ -30,12 +37,9 @@ void MotionDetection::end(void){
};
IMUResult MotionDetection::getAcceleration(){
IMUResult result;
result.x = readRegister(ACCEL_DATA_X_HIGH)<<8;
result.x |= readRegister(ACCEL_DATA_X_LOW);
result.y = readRegister(ACCEL_DATA_Y_HIGH)<<8;
result.y |= readRegister(ACCEL_DATA_Y_LOW);
result.z = readRegister(ACCEL_DATA_Z_HIGH)<<8;
result.z |= readRegister(ACCEL_DATA_Z_LOW);
result.x = readRegister(ACCEL_DATA_X_HIGH)<<8 | readRegister(ACCEL_DATA_X_LOW);
result.y = readRegister(ACCEL_DATA_Y_HIGH)<<8 | readRegister(ACCEL_DATA_Y_LOW);
result.z = readRegister(ACCEL_DATA_Z_HIGH)<<8 | readRegister(ACCEL_DATA_Z_LOW);
return result;
};
IMUResult MotionDetection::getRotation(){
@@ -58,6 +62,106 @@ int8_t MotionDetection::getWhoAmI(){
return readRegister(WHO_AM_I);
};
bool MotionDetection::isShaken(uint32_t threshold ,uint8_t axis){
IMUResult measurment1;
IMUResult measurment2;
uint count = 0;
for(uint i = 0;i<20;i++){
measurment1 = this->getAcceleration();
delayMicroseconds(10);
measurment2 = this->getAcceleration();
if(
(((axis && xAxis) > 0) && (abs(abs(measurment1.x)-abs(measurment2.x))>threshold)) ||
(((axis && yAxis) > 0) && (abs(abs(measurment1.y)-abs(measurment2.y))>threshold)) ||
(((axis && zAxis) > 0) && (abs(abs(measurment1.z)-abs(measurment2.z))>threshold))){
count++;
}
delayMicroseconds(15);
}
return (count > 6);
};
void MotionDetection::calibrateZAxis(uint gforceValue){
this->gForceCalib = gforceValue;
};
Orientation MotionDetection::getTilt(){
uint tolerance = 200;
IMUResult reading = this->getAcceleration();
bool flipped = reading.z < 0;
float accelrationStrenght = sqrt(reading.x*reading.x+reading.y*reading.y+reading.z*reading.z);
//check if reading is valid
if (abs(accelrationStrenght-this->gForceCalib) > tolerance ){
//total accelration is not gravitational force, error
return Orientation{INT_MAX,INT_MAX};
}
//calculates the angle between the two axis, therefore value between 0-90
int yAngle;
int xAngle;
if(reading.z != 0){
yAngle = atan(float(reading.x)/reading.z)*180/3.1415+0.5;
xAngle = atan(float(reading.y)/reading.z)*180/3.1415+0.5;
} else {
yAngle = 90*(reading.x > 0) - (reading.x < 0);
xAngle = 90*(reading.y > 0) - (reading.y < 0);
}
//shift quadrants depending on signum
//esp is facing down (normal position)
if (reading.z > 0){
if(reading.y < 0){
xAngle = xAngle+180;
} else{
xAngle = -1*(180-xAngle);
}
if(reading.x < 0){
yAngle = yAngle+180;
} else{
yAngle = -1*(180-yAngle);
}
//yAngle = -1*yAngle-90;
}
return Orientation{xAngle,yAngle};
};
Direction MotionDetection::getTiltDirection(uint tolerance){
if (this->getAcceleration().z > 0){
return Flipped;
}
Orientation Rot = this->getTilt();
Serial.println(Rot.xRotation);
Serial.println(Rot.xRotation == INT_MAX);
if ((Rot.xRotation == INT_MAX)){
return Error;
}
if(abs(abs(Rot.xRotation)-abs(Rot.yRotation))>tolerance){
//determine which axis is more tiltet
if (abs(Rot.xRotation)>abs(Rot.yRotation)){
//test if dezibot is tilted left or right
if (Rot.xRotation > 0){
return Right;
} else {
return Left;
}
} else {
//test if robot is tilted front or back
if (Rot.yRotation > 0){
return Front;
} else {
return Back;
}
}
} else {
//dezibot is (with tolerance) leveled
return Neutral;
}
};
uint8_t MotionDetection::cmdRead(uint8_t reg){
return (CMD_READ | (reg & ADDR_MASK));
};
@@ -65,7 +169,7 @@ uint8_t MotionDetection::cmdWrite(uint8_t reg){
return (CMD_WRITE | (reg & ADDR_MASK));
};
int8_t MotionDetection::readRegister(uint8_t reg){
uint8_t MotionDetection::readRegister(uint8_t reg){
handler->beginTransaction(SPISettings(frequency,SPI_MSBFIRST,SPI_MODE0));
digitalWrite(34,LOW);
uint8_t result;

View File

@@ -17,7 +17,26 @@ struct IMUResult{
int16_t y;
int16_t z;
};
enum Axis{
xAxis = 0x01,
yAxis = 0x02,
zAxis = 0x04
};
struct Orientation{
int xRotation;
int yRotation;
};
enum Direction{
Front,
Left,
Right,
Back,
Neutral,
Flipped,
Error
};
class MotionDetection{
protected:
@@ -48,16 +67,19 @@ protected:
static const uint8_t WHO_AM_I = 0x75;
static const uint frequency = 10000000;
static const uint16_t defaultShakeThreshold = 500;
uint16_t cmdRead(uint8_t regHigh,uint8_t regLow);
uint16_t cmdWrite(uint8_t regHigh,uint8_t regLow);
uint8_t cmdRead(uint8_t reg);
uint8_t cmdWrite(uint8_t reg);
int8_t readRegister(uint8_t reg);
uint8_t readRegister(uint8_t reg);
int16_t readDoubleRegister(uint8_t lowerReg);
SPIClass * handler = NULL;
uint gForceCalib = 4050;
public:
@@ -83,21 +105,21 @@ public:
*
* @return IMUResult that contains the new read values
*/
IMUResult getAcceleration();
IMUResult getAcceleration(void);
/**
* @brief Triggers a new reading of the gyroscope and reads the values from the imu
*
* @return IMUResult
*/
IMUResult getRotation();
IMUResult getRotation(void);
/**
* @brief Reads the current On Chip temperature of the IMU
*
* @return normalized temperature in degree Centigrade
*/
float getTemperature();
float getTemperature(void);
/**
* @brief Returns the value of reading the whoAmI register
@@ -105,6 +127,62 @@ public:
*
* @return the value of the whoami register of the ICM-42670
*/
int8_t getWhoAmI();
int8_t getWhoAmI(void);
/**
* @brief Detects if at the time of calling is shaken. Therefore the sum over all accelerationvalues is calculated
* and checked against threshold. If sum > threshold a shake is detected, else not
*
* @param threshold (optional) the level of acceleration that must be reached to detect a shake
* @param axis (optional) select which axis should be used for detection. Possible values ar xAxis,yAxis,zAxis
* It's possible to combine multiple axis with the bitwise or Operator |
* For Example: to detect x and y axis: axis = xAxis|yAxis
*
* @return true if a shake is detected, false else
*/
bool isShaken(uint32_t threshold = defaultShakeThreshold,uint8_t axis = xAxis|yAxis|zAxis);
/**
* @brief calculates how the robot is tilted. It is set, that when the robot is placed normally on a flat table, the result will be (0,0)
* Tilting the robot, so that the front leg is deeper than the other to results in an increasing degrees, tilting the front leg up will increase negativ degrees
* Tilting the robot to the right will increase the degrees until 180° (upside down), tilting it left will result in increasing negativ degrees (-1,-2,...,-180).
* On the top there is a jump of the values from 180->-180 and vice versa.
*
* Precision is rounded to 1 deg steps
*
* @attention The results are only valid, if the robot is not moved in any way during the measurment, as the calculation is made by using the accelration values.
* If it's detected, that the robot is accelerated while measuring, the method will return max(int).
* Please note that the imu is pretty sensitiv, even walking next to the table may influcene the result.
*
*/
Orientation getTilt();
/**
* @brief Checks in which direction (Front, Left, Right, Back) the robot is tilted.
*
* @attention Does only work if the robot is not moving
*
* @param tolerance (optional, default = 10) how many degrees can the robot be tilted, and still will be considerd as neutral.
*
*
* @return Direction the direction in that the robot is tilted most. Front is onsiderd as the direction of driving.
* If robot is not tilted more than the tolerance in any direction, return is Neutral.
* If Robot is upside down, return is Flipped.
* If Robot is moved, return is Error
*/
Direction getTiltDirection(uint tolerance = 10);
/**
* can be used to set a custom value for the gforceReading of the zaxis, which will improve the getTiltFunction.
*
* @attention this method is not persisten, so the value is not stored when the programm is restarted / the robot is powerd off
*
* @param gforceValue the value the IMU returns for the gravitationforce -> to get this value, place the robot on a leveled surface
* and read the value getAcceleration().z
*/
void calibrateZAxis(uint gforceValue);
};
#endif //MotionDetection

View File

@@ -6,6 +6,7 @@ MultiColorLight::MultiColorLight():rgbLeds(ledAmount,ledPin){
void MultiColorLight::begin(void){
rgbLeds.begin();
this->turnOffLed();
};
void MultiColorLight::setLed(uint8_t index , uint32_t color){
@@ -60,7 +61,6 @@ void MultiColorLight::blink(uint16_t amount,uint32_t color, leds leds, uint32_t
MultiColorLight::turnOffLed(leds);
vTaskDelay(interval);
}
};
void MultiColorLight::turnOffLed(leds leds){