Hackster is hosting Impact Spotlights: Smart Home. Watch now!
Infineon Team
Published © MIT

Whack!T - Whack-a-mole enabled by XMC for Arduino

Whack!T is an Arduino-powered Whack-a-Mole game with pneumatic action and smart sensing, creating a unique gaming experience!

AdvancedFull instructions provided16 hours792

Things used in this project

Hardware components

TLE493D-P3xx-MS2GO
Infineon TLE493D-P3xx-MS2GO
×4
KIT XMC47 RELAX LITE V1
Infineon KIT XMC47 RELAX LITE V1
×1
DC Motor Shield with TLE94112ES for Arduino
Infineon DC Motor Shield with TLE94112ES for Arduino
×1
Kit2GO PRESSURE DPS368
Infineon Kit2GO PRESSURE DPS368
×2
9V 1A Switching Wall Power Supply
9V 1A Switching Wall Power Supply
×1
TLD5190 VOLT DEMO
×1
S2GO SECURITY OPTIGA M
Infineon S2GO SECURITY OPTIGA M
×1
Piezo-Buzzer Modul
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
3D Printer (generic)
3D Printer (generic)
Laser cutter (generic)
Laser cutter (generic)
Premium Female/Male 'Extension' Jumper Wires, 40 x 3" (75mm)
Premium Female/Male 'Extension' Jumper Wires, 40 x 3" (75mm)

Story

Read more

Custom parts and enclosures

Inventor File Whack!T

Open this file with inventor 2023

Inventor File Hammer

Open this file with Inventor 2023

Inventor File hammer cover

Open this file with Inventor 2023

Hammer cover.stl

Sketchfab still processing.

Sensor Holder.stl file for P3xx

Sketchfab still processing.

holder for buck converter

Sketchfab still processing.

Schematics

whacktdemo_P5FgkVQ3bw.fzz

Code

Test snippet: 7-segment display

Arduino
Test code for the 7-segment display.
/*
 Controlling large 7-segment displays
 By: Nathan Seidle
 SparkFun Electronics
 Date: February 25th, 2015
 License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).

 This code demonstrates how to post two numbers to a 2-digit display usings two large digit driver boards.

 Here's how to hook up the Arduino pins to the Large Digit Driver IN
 
 There are two connectors on the Large Digit Driver. 'IN' is the input side that should be connected to
 your microcontroller (the Arduino). 'OUT' is the output side that should be connected to the 'IN' of addtional
 digits.
 
 Each display will use about 150mA with all segments and decimal point on.
 
*/

//GPIO declarations
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
byte segmentClock = 52;
byte segmentLatch = 50;
byte segmentData = 51;

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void setup()
{
  Serial.begin(9600);
  Serial.println("Large Digit Driver Example");

  pinMode(segmentClock, OUTPUT);
  pinMode(segmentData, OUTPUT);
  pinMode(segmentLatch, OUTPUT);

  digitalWrite(segmentClock, LOW);
  digitalWrite(segmentData, LOW);
  digitalWrite(segmentLatch, LOW);
}

int number = 0;

void loop()
{
  showNumber(number); //Test pattern
  number++;
  number %= 100; //Reset x after 99
  
  Serial.println(number); //For debugging
  
  delay(500);
}

//Takes a number and displays 2 numbers. Displays absolute value (no negatives)
void showNumber(float value)
{
  int number = abs(value); //Remove negative signs and any decimals

  //Serial.print("number: ");
  //Serial.println(number);

  for (byte x = 0 ; x < 2 ; x++)
  {
    int remainder = number % 10;

    postNumber(remainder, false);

    number /= 10;
  }

  //Latch the current segment data
  digitalWrite(segmentLatch, LOW);
  digitalWrite(segmentLatch, HIGH); //Register moves storage register on the rising edge of RCK
}

//Given a number, or '-', shifts it out to the display
void postNumber(byte number, boolean decimal)
{
  //    -  A
  //   / / F/B
  //    -  G
  //   / / E/C
  //    -. D/DP

#define a  1<<0
#define b  1<<6
#define c  1<<5
#define d  1<<4
#define e  1<<3
#define f  1<<1
#define g  1<<2
#define dp 1<<7

  byte segments;

  switch (number)
  {
    case 1: segments = b | c; break;
    case 2: segments = a | b | d | e | g; break;
    case 3: segments = a | b | c | d | g; break;
    case 4: segments = f | g | b | c; break;
    case 5: segments = a | f | g | c | d; break;
    case 6: segments = a | f | g | e | c | d; break;
    case 7: segments = a | b | c; break;
    case 8: segments = a | b | c | d | e | f | g; break;
    case 9: segments = a | b | c | d | f | g; break;
    case 0: segments = a | b | c | d | e | f; break;
    case ' ': segments = 0; break;
    case 'c': segments = g | e | d; break;
    case '-': segments = g; break;
  }

  if (decimal) segments |= dp;

  //Clock these bits out to the drivers
  for (byte x = 0 ; x < 8 ; x++)
  {
    digitalWrite(segmentClock, LOW);
    digitalWrite(segmentData, segments & 1 << (7 - x));
    digitalWrite(segmentClock, HIGH); //Data transfers to the register on the rising edge of SRCK
  }
}

Test snippet: Random number generator

Arduino
Test code for Optiga-based random number generator.
#include "OPTIGATrustM.h"

#define RND_MAXLENGTH 8 

// Disable colored output
#define SUPPRESSCOLORS
#include "fprint.h"

void setup() 
{
  uint32_t ret = 0;
  
  // Initialise a serial port for debug output
  Serial.begin(115200);
  delay(1000); // Wait for the serial port to initialize
  Serial.println("Initializing ... ");

  // Initialise an OPTIGA Trust X Board
  printGreen("Begin to trust ... ");
  ret = trustM.begin();
  if (ret) {
    printlnRed("Failed");
    while (true); // Stop execution if initialization fails
  }
  printlnGreen("OK");

  // Speed up the board (from 6 mA to 15 mA)
  printGreen("Setting current limit to 15 mA ... ");
  ret = trustM.setCurrentLimit(8);
  if (ret) {
    printlnRed("Failed");
    while (true); // Stop execution if setting current limit fails
  }
  printlnGreen("OK");
}

// Function to output the result
static void output_result(char* tag, uint32_t tstamp, uint8_t* in, uint16_t in_len)
{
  printGreen("[OK] | Command executed in "); 

  printMagenta(tag); // Output the tag

  HEXDUMP(in, in_len); // Dump the content of the input buffer in hexadecimal format
}

void loop()
{
  uint32_t ret = 0;
  uint8_t *rnd = new uint8_t[RND_MAXLENGTH]; // Allocate memory for the random number array
  
  // Initialize memory area to 0
  memset(rnd, 0, RND_MAXLENGTH);

  // Get a random number from the Trust M module
  ret = trustM.getRandom(RND_MAXLENGTH, rnd);
  if (ret) {
    printlnRed("Failed");
    while (true); // Stop execution if getting random number fails
  }

  // Convert the byte array to an int64_t number
  int64_t random_value = 0;
  random_value = convertByteArrayToInt64(rnd, 8);

  // Map the value to the range 1-9
  uint8_t random_number = 0;
  random_number = (random_value % 9) + 1;
  if(random_number > 9)
  {
    random_number = random_number % 9 + 1; // Ensure the random number is between 1 and 9
  }
  Serial.print("Random number between 1 and 9: ");
  Serial.println(random_number);
  Serial.println();
  
  delete rnd; // Free the allocated memory
}

// Function to convert a byte array to an int64_t number
int64_t convertByteArrayToInt64(uint8_t* array, size_t length) {
    int64_t result = 0;
    for (size_t i = 0; i < length; ++i) {
        result = (result << 8) | array[i]; // Shift left and add the next byte
    }
    return result;
}

Test snippet: DPS368 sensor

Arduino
Test code for the DPS368 air pressure sensor.
#include <Dps3xx.h>

/**
 * @details This example shows how to read temperature and pressure in a loop with a
 *          high oversampling rate.
 *          The oversampling rate can be set between 0 and 7 the higher the value the
 *          more precise the value is.
 */

// Dps3xx Object
Dps3xx Dps3xxPressureSensor = Dps3xx();
Dps3xx Dps3xxPressureSensor2 = Dps3xx();
float difference_sensor=0;

void setup()
{
  Serial.begin(9600);
  while (!Serial);

  /*
   * Call begin to initialize Dps3xxPressureSensor
   * The parameter 0x76 is the bus address. The default address is 0x77 and does not need to be given.
   * Dps3xxPressureSensor.begin(Wire, 0x76);
   * Use the line below instead of the one above to use the default I2C address.
   * if you are using the Pressure 3 click Board, you need 0x76
   */
  Dps3xxPressureSensor.begin(Wire1, 0x76);
  Dps3xxPressureSensor2.begin(Wire1);

  Serial.println("Init complete!");
  delay(5000);
  difference_sensor=calc_difference();
}
uint8_t oversampling = 7;

void loop()
{
  float hight_now=hight();
  Serial.println(hight_now);
 
  if(abs(hight_now)>=10)
  {
    Serial.print("Hammer up");
  }
  else
  {
    Serial.print("Hammer down");
  }
  delay(500);
}

float calc_difference()
{
  float pressure_init_1=0;
  float pressure_init_2=0;
  int ret=0;
  float difference=0;
  do
  {
    ret = Dps3xxPressureSensor.measurePressureOnce(pressure_init_1, oversampling);

  }
  while(ret!=0);

  do
  {
    ret = Dps3xxPressureSensor2.measurePressureOnce(pressure_init_2, oversampling);
    delay(500);
  }
  while(ret!=0);

  difference=pressure_init_2-pressure_init_1;

  return difference;
}

float hight()
{
  float pressure1;
  float pressure2;
  float heightDifference;
  
  int16_t ret;
  const float rho = 1.225; // kg/m 
  const float g = 9.81; // m/s 

  Serial.println();

 do
  {
    ret = Dps3xxPressureSensor.measurePressureOnce(pressure1, oversampling);
    delay(500);
    Serial.print(ret);
  }
  while(ret!=0);


 do
  {
    ret = Dps3xxPressureSensor2.measurePressureOnce(pressure2, oversampling);
    delay(500);
    Serial.print(ret);
  }
  while(ret!=0);

  heightDifference =abs((pressure1 - pressure2) / (rho * g) * 100)-abs(difference_sensor/ (rho * g) * 100); // in Zentimetern
  return heightDifference;
}

Test snippet: TLE94112 Multi-Half-Bridge

Arduino
Test code for the TLE94112ES multi-half-bridge driver.
#include <tle94112-ino.hpp>
#include <tle94112-motor-ino.hpp>
#include "SPI.h"

// Tle94112 Object
Tle94112Ino controller = Tle94112Ino();

Tle94112Motor aktor1(controller);
Tle94112Motor aktor2(controller);
Tle94112Motor aktor3(controller);
Tle94112Motor aktor4(controller);
Tle94112Motor aktor5(controller);
Tle94112Motor aktor6(controller);
Tle94112Motor aktor7(controller);
Tle94112Motor aktor8(controller);
Tle94112Motor aktor9(controller);
Tle94112Motor kompressor(controller);
/*
Tle94112Motor aktor1(motor1.HIGHSIDE, controller.TLE_HB1);
Tle94112Motor aktor2(tle94112, tle94112.TLE_NOPWM);
Tle94112Motor aktor3(tle94112, tle94112.TLE_NOPWM);
Tle94112Motor aktor4(tle94112, tle94112.TLE_NOPWM);
Tle94112Motor aktor5(tle94112, tle94112.TLE_NOPWM);
Tle94112Motor aktor6(tle94112, tle94112.TLE_NOPWM);
Tle94112Motor aktor7(tle94112, tle94112.TLE_NOPWM);
Tle94112Motor aktor8(tle94112, tle94112.TLE_NOPWM);
Tle94112Motor aktor9(tle94112, tle94112.TLE_NOPWM);
Tle94112Motor kompressor(tle94112, tle94112.TLE_PWM1);*/

void push(int i)
{
  switch (i) {
    case 1:    // your hand is on the sensor
       aktor1.start(255);
       delay(1000);
       aktor1.stop(0);  
      break;
    case 2:    // your hand is close to the sensor
       aktor2.start(255);
       delay(1000);
       aktor2.stop(0);  
      break;
    case 3:    // your hand is a few inches from the sensor
       aktor3.start(255);
       delay(1000);
       aktor3.stop(0);  
      break;
    case 4:    // your hand is nowhere near the sensor
       aktor4.start(255);
       delay(1000);
       aktor4.stop(0);  
      break;
    case 5:    // your hand is on the sensor
       aktor5.start(255);
       delay(1000);
       aktor5.stop(0);  
      break;
    case 6:    // your hand is close to the sensor
       aktor6.start(255);
       delay(1000);
       aktor6.stop(0);  
      break;
    case 7:    // your hand is a few inches from the sensor
       aktor7.start(255);
       delay(1000);
       aktor7.stop(0);  
      break;
    case 8:    // your hand is nowhere near the sensor
       aktor8.start(255);
       delay(1000);
       aktor8.stop(0);  
      break;
    case 9:    // your hand is nowhere near the sensor
       aktor9.start(255);
       delay(1000);
       aktor9.stop(0);  
      break;
  }
  
}

void setup()
{
  Serial.begin(9600);
  // call begin for the TLE94112 firs
  controller.begin();
  
  aktor1.connect(aktor1.HIGHSIDE,controller.TLE_HB8);  
  aktor2.connect(aktor2.HIGHSIDE,controller.TLE_HB7);
  aktor3.connect(aktor3.HIGHSIDE,controller.TLE_HB11);
  aktor4.connect(aktor4.HIGHSIDE,controller.TLE_HB12);  
  aktor5.connect(aktor5.HIGHSIDE,controller.TLE_HB9);
  aktor6.connect(aktor6.HIGHSIDE,controller.TLE_HB10);
  aktor7.connect(aktor7.HIGHSIDE,controller.TLE_HB6);  
  aktor8.connect(aktor8.HIGHSIDE,controller.TLE_HB3);
  aktor9.connect(aktor9.HIGHSIDE,controller.TLE_HB4);
  kompressor.connect(kompressor.HIGHSIDE,controller.TLE_HB5);  
  kompressor.connect(kompressor.HIGHSIDE,controller.TLE_HB2);
  kompressor.connect(kompressor.HIGHSIDE,controller.TLE_HB1);

  aktor1.begin();
  aktor2.begin();
  aktor3.begin();
  aktor4.begin();
  aktor5.begin();
  aktor6.begin();
  aktor7.begin();
  aktor8.begin();
  aktor9.begin();
  kompressor.begin();
}

void loop(){


  
  if (Serial.available() > 0) {
    kompressor.start(255);
    delay(1000);
    kompressor.stop(0);
    // Eingehende Zahl als String einlesen
    String input = Serial.readStringUntil('\n');
    // Versuch, den String in eine Zahl zu konvertieren
    int zahl = input.toInt();

    // berprfen, ob die Konvertierung erfolgreich war
    if (input.length() > 0 && zahl == 0 && input.charAt(0) != '0') {
      Serial.println("Ungltige Eingabe! Bitte eine gltige Zahl eingeben.");
    } else {
      Serial.print("Du hast die Zahl eingegeben: ");
      push(zahl);
      Serial.println(zahl);
    }
  }
/*  kompressor.start(255);
  delay(1000);
  kompressor.start(0);
  aktor8.start(255);
  delay(1000);
  aktor8.stop(0);
*/
  /*push(9);
  push(8);
  push(7);
  push(6);
  push(5);
  push(4);
  push(3);
  push(2);
  push(1);
  */
}

 

Test snippet: 4x TLE493D 3D Magnetic Sensors

Arduino
Test code to communicate with four TLE493D 3D magnetic sensors.
/** Project CPP includes. */
#include "TLx493D_inc.hpp"
/** Define which sensors should be activated */
#define SENSOR_1_ACTIVE
#define SENSOR_2_ACTIVE  
#define SENSOR_3_ACTIVE
#define SENSOR_4_ACTIVE 
#define numavg 50
using namespace ifx::tlx493d;

/** Definition of the power and chip select pins for four sensors. */
const uint8_t CHIP_SELECT_PIN_1 = 88;
const uint8_t CHIP_SELECT_PIN_2 = 91;
const uint8_t CHIP_SELECT_PIN_3 = 89;
const uint8_t CHIP_SELECT_PIN_4 = 92;

/** Declaration of the sensor objects. */
TLx493D_P3I8 sensor1(SPI2);
TLx493D_P3I8 sensor2(SPI2);
TLx493D_P3I8 sensor3(SPI2);
TLx493D_P3I8 sensor4(SPI2);


void average_sensor_value(uint sensor, double *sumTemp, double *sumX, double *sumY, double *sumZ)
{
    double sumTemp1 = 0.0, sumTemp2 = 0.0, sumTemp3 = 0.0, sumTemp4 = 0.0;
    double sumX1 = 0, sumY1 = 0, sumZ1 = 0;
    double sumX2 = 0, sumY2 = 0, sumZ2 = 0;
    double sumX3 = 0, sumY3 = 0, sumZ3 = 0;
    double sumX4 = 0, sumY4 = 0, sumZ4 = 0;
    double temp, valX, valY, valZ;

    unsigned long startTime = millis(); // Start time

    for (int i = 0; i < numavg; ++i) {
        if(sensor == 1)
        {
        sensor1.getTemperature(&temp);
        sensor1.getMagneticField(&valX, &valY, &valZ);
        sumTemp1 += temp;
        sumX1 += valX;
        sumY1 += valY;
        sumZ1 += valZ;
        if(i == numavg-1)
        {
            *sumTemp = sumTemp1/numavg;
            *sumX = sumX1/numavg;
            *sumY = sumY1/numavg;
            *sumZ = sumZ1/numavg;
        }
        }
        else if(sensor == 2)
        {
        sensor2.getTemperature(&temp);
        sensor2.getMagneticField(&valX, &valY, &valZ);
        sumTemp2 += temp;
        sumX2 += valX;
        sumY2 += valY;
        sumZ2 += valZ;
        if (i == numavg-1)
        {
            *sumTemp = sumTemp2/numavg;
            *sumX = sumX2/numavg;
            *sumY = sumY2/numavg;
            *sumZ = sumZ2/numavg;
        }
        
        }

        else if(sensor == 3)
        {
        sensor3.getTemperature(&temp);
        sensor3.getMagneticField(&valX, &valY, &valZ);
        sumTemp3 += temp;
        sumX3 += valX;
        sumY3 += valY;
        sumZ3 += valZ;
        if (i == numavg-1)
        {
            *sumTemp = sumTemp3/numavg;
            *sumX = sumX3/numavg;
            *sumY = sumY3/numavg;
            *sumZ = sumZ3/numavg;
        }
        }
        else if(sensor == 4)
        {
        sensor4.getTemperature(&temp);
        sensor4.getMagneticField(&valX, &valY, &valZ);
        sumTemp4 += temp;
        sumX4 += valX;
        sumY4 += valY;
        sumZ4 += valZ;
        if (i == numavg-1)
        {
           *sumTemp = sumTemp4/numavg;
            *sumX = sumX4/numavg;
            *sumY = sumY4/numavg;
            *sumZ = sumZ4/numavg;
        }
        }
    }

    // End time
    unsigned long endTime = millis();
    unsigned long loopDuration = endTime - startTime;
    Serial.print("Loop duration: ");
    Serial.println(loopDuration);
}


void setup() {
    Serial.begin(115200);
    delay(3000);
    SPI2.begin();
    
#ifdef SENSOR_1_ACTIVE
    // Setup for sensor 1
    sensor1.setSelectPin(CHIP_SELECT_PIN_1, OUTPUT, INPUT, LOW, HIGH, 0, 0,0,5);
    sensor1.begin(true, true);
#endif

#ifdef SENSOR_2_ACTIVE
    // Setup for sensor 2
    sensor2.setSelectPin(CHIP_SELECT_PIN_2, OUTPUT, INPUT, LOW, HIGH, 0, 0,0,5);
    sensor2.begin(true, true);
#endif

#ifdef SENSOR_3_ACTIVE
    // Setup for sensor 3
    sensor3.setSelectPin(CHIP_SELECT_PIN_3, OUTPUT, INPUT, LOW, HIGH, 0, 0,0,5);
    sensor3.begin(true, true);
#endif

#ifdef SENSOR_4_ACTIVE
    // Setup for sensor 4
    sensor4.setSelectPin(CHIP_SELECT_PIN_4, OUTPUT, INPUT, LOW, HIGH, 0, 0,0,5);
    sensor4.begin(true, true);
#endif

    Serial.print("setup done.\n");
}

/** In the loop we're reading out the temperature value (in C) as well as the magnetic fields values in X, Y, Z-direction (in mT).
 *  We're also reading out the raw temperature value (in LSB).
 */
void loop() {
    double avg_temp=0; double avg_x=0; double avg_y=0; double avg_z=0;

    
#ifdef SENSOR_1_ACTIVE
    // Read and print data from sensor 1
    sensor1.printRegisters();
    average_sensor_value(1, &avg_temp, &avg_x, &avg_y, &avg_z);
     Serial.print("Sensor 1:");
    Serial.print("Sensor 1 - Temp: "); Serial.print(avg_temp); Serial.print(" C, ");
    Serial.print("Magnetic Field - X: "); Serial.print(avg_x); Serial.print(" mT, ");
    Serial.print("Y: "); Serial.print(avg_y); Serial.print(" mT, ");
    Serial.print("Z: "); Serial.println(avg_z); Serial.print(" mT\n");
#endif

#ifdef SENSOR_2_ACTIVE

    average_sensor_value(2, &avg_temp, &avg_x, &avg_y, &avg_z);
    Serial.print("Sensor 2:");
    Serial.print("Sensor 2 - Temp: "); Serial.print(avg_temp); Serial.print(" C, ");
    Serial.print("Magnetic Field - X: "); Serial.print(avg_x); Serial.print(" mT, ");
    Serial.print("Y: "); Serial.print(avg_y); Serial.print(" mT, ");
    Serial.print("Z: "); Serial.println(avg_z); Serial.print(" mT\n");
#endif

#ifdef SENSOR_3_ACTIVE

    average_sensor_value(3, &avg_temp, &avg_x, &avg_y, &avg_z);
    Serial.print("Sensor 3:");
    Serial.print("Sensor 3 - Temp: "); Serial.print(avg_temp); Serial.print(" C, ");
    Serial.print("Magnetic Field - X: "); Serial.print(avg_x); Serial.print(" mT, ");
    Serial.print("Y: "); Serial.print(avg_y); Serial.print(" mT, ");
    Serial.print("Z: "); Serial.println(avg_z); Serial.print(" mT\n");
#endif

#ifdef SENSOR_4_ACTIVE

    average_sensor_value(4, &avg_temp, &avg_x, &avg_y, &avg_z);
    Serial.print("Sensor 4:");
    Serial.print("Sensor 4 - Temp: "); Serial.print(avg_temp); Serial.print(" C, ");
    Serial.print("Magnetic Field - X: "); Serial.print(avg_x); Serial.print(" mT, ");
    Serial.print("Y: "); Serial.print(avg_y); Serial.print(" mT, ");
    Serial.print("Z: "); Serial.println(avg_z); Serial.print(" mT\n");
#endif

}

Game code: whackit.ino

Arduino
Main application code: Place into an folder with the same name, together with all *.hpp files.
/** Project CPP includes. */ 
bool test=0;
bool start_counting=false;

#define sensoren 4
#define werte 3

#define gameduration 30

unsigned long startMillis;
const unsigned long countdownDuration = 15000;  // 15 Sekunden in Millisekunden
int gametime=15; //15s gametime

int randomdelay=0;
int delaycounter=0;
bool delaymarker=false;
uint8_t counter_interrupt=0;
int id_index = 0;
bool hit_marker=true;
uint8_t game_hit_counter=0;
bool hammer_oben=false;
int hit_merken=0;

#include "display.hpp"
#include "TLx493D_inc.hpp"
#include "airpressure_sensor.hpp"
#include "3d_sensor.hpp"
#include "push.hpp"

#include "game_matirx.hpp"


int merken=0;


void setup() {
  Serial.begin(115200);
  delay(6000);
  init_display();
  init_dps_sensor();
  init_3d_sensor();
  delay(1000);
  measure_initial_values();
  init_mhb();

  kompressor.start(255);
  delay(2000); //for airpressure buildup :)

  Serial.print("init done");

  Serial.println("vor handler");

  Serial.println("nach handler");
  Serial.print("Init done!");

  test=1;
  delay(500);
}




void loop()
  {


  gametime=getRemainingSeconds();

    if(start_counting==true&&gametime>=0)
    {
      if(gametime>=0)
      { 
        showNumber(gametime);
      }
        if(gametime==0)
        {
          hit_merken=game_hit_counter;
          game_hit_counter=0;
          start_counting=false;
          gametime=15;
        }
        calculate_average(piston_now);
        if(compare_difference(piston_now, 0.1)==true)  //change this threashold of needed
        {
          hit_marker=true;
          game_hit_counter++;
        }

        if(hit_marker==true)
        {
          push(random(1,10));
          hit_marker=false;
        }
      
      }
      else
      {
        showNumber(hit_merken);
        start_game();
        merken=0;
        
      }
      return;
  }




int getRemainingSeconds() {
  long currentMillis = millis();  // Aktuelle Zeit in Millisekunden
 long elapsedMillis = currentMillis - startMillis;  // Berechne die vergangene Zeit

  if (elapsedMillis >= countdownDuration) {
    return 0;  // Countdown beendet
  } else {
    return (countdownDuration - elapsedMillis) / 1000;  // Verbleibende Sekunden
  }
}

Game code: 3d_sensor.hpp

Arduino
#include "TLx493D_inc.hpp"

#define sensoren 4
#define werte 3

double piston_now[sensoren][werte],piston_up[sensoren][werte], sensor_values_1_time[sensoren][werte], senor_value_polar[sensoren][werte] = {0.0, 0.0, 0.0,
                                                                                                                0.0, 0.0, 0.0,
                                                                                                                0.0, 0.0, 0.0,
                                                                                                                0.0, 0.0, 0.0};
double initial_sensor_values[sensoren][werte] = {0.0, 0.0, 0.0,
                                                 0.0, 0.0, 0.0,
                                                 0.0, 0.0, 0.0,
                                                 0.0, 0.0, 0.0};

using namespace ifx::tlx493d;

TLx493D_P3I8 sensor1(SPI2);
TLx493D_P3I8 sensor2(SPI2);
TLx493D_P3I8 sensor3(SPI2);
TLx493D_P3I8 sensor4(SPI2);

const uint8_t CHIP_SELECT_PIN_1 = 88;
const uint8_t CHIP_SELECT_PIN_2 = 91;
const uint8_t CHIP_SELECT_PIN_3 = 89;
const uint8_t CHIP_SELECT_PIN_4 = 92;



double val[4][3] = {0.0, 0.0, 0.0,
                    0.0, 0.0, 0.0,
                    0.0, 0.0, 0.0,
                    0.0, 0.0, 0.0};

void init_3d_sensor()
{
  SPI2.begin();
  delay(3000);
  Serial.print("Init Sensor 1 begin");
  sensor1.setSelectPin(CHIP_SELECT_PIN_1, OUTPUT, INPUT, LOW, HIGH, 0, 0,0,5);
  sensor1.begin(true, true);
  Serial.print("Init Sensor 1 finished");
  
  delay(1000);
  Serial.print("Init Sensor 2 begin");
  sensor2.setSelectPin(CHIP_SELECT_PIN_2, OUTPUT, INPUT, LOW, HIGH, 0, 0,0,5);
  sensor2.begin(true, true);
  Serial.print("Init Sensor 2 finished");

  delay(1000);
  Serial.print("Init Sensor 3 begin");
  sensor3.setSelectPin(CHIP_SELECT_PIN_3, OUTPUT, INPUT, LOW, HIGH, 0, 0,0,5);
  sensor3.begin(true, true);
  Serial.print("Init Sensor 3 finished");


  delay(1000); 
  Serial.print("Init Sensor 4 begin");
  sensor4.setSelectPin(CHIP_SELECT_PIN_4, OUTPUT, INPUT, LOW, HIGH, 0, 0,0,5);
  sensor4.begin(true, true);
  Serial.print("Init Sensor 4 finished");


  sensor1.setSensitivity(TLx493D_EXTRA_SHORT_RANGE_e);
  sensor2.setSensitivity(TLx493D_EXTRA_SHORT_RANGE_e);
  sensor3.setSensitivity(TLx493D_EXTRA_SHORT_RANGE_e);
  sensor4.setSensitivity(TLx493D_EXTRA_SHORT_RANGE_e);
  
  Serial.print("setup sensors done.\n");
}

void convertToSpherical(double x, double y, double z, double &r, double &theta, double &phi) {
  // Calculate the radius
  r = sqrt(x * x + y * y + z * z);

  // Calculate the azimuth angle (theta)
  theta = atan2(y, x) * 180.0 / PI; // Convert to degrees

  // Calculate the polar angle (phi)
  phi = acos(z / r) * 180.0 / PI; // Convert to degrees
}

void sensor_value(double (&sensor_values)[sensoren][werte])
{
  sensor1.getMagneticField(&sensor_values[0][0], &sensor_values[0][1], &sensor_values[0][2]);
  sensor2.getMagneticField(&sensor_values[1][0], &sensor_values[1][1], &sensor_values[1][2]);
  sensor3.getMagneticField(&sensor_values[2][0], &sensor_values[2][1], &sensor_values[2][2]);
  sensor4.getMagneticField(&sensor_values[3][0], &sensor_values[3][1], &sensor_values[3][2]);
}

void calculate_average(double(&sensor_average)[sensoren][werte]) {
  double sum_vals[sensoren][werte] = {0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0};
  for (int i = 0; i < 10; ++i) {
    sensor_value(sensor_values_1_time);
    for (int j = 0; j < sensoren; j++) {
      for (int k = 0; k < werte; k++) {
        sum_vals[j][k] += sensor_values_1_time[j][k];
      }
    }
  }
  

  for (int j = 0; j < sensoren; j++) {
    for (int k = 0; k < werte; k++) {
      sensor_average[j][k] = sum_vals[j][k] / 10.0;
    }
  }
}

double converttobetrag(double x, double y, double z) {
  return sqrt(x * x + y * y + z * z);
}
double sensor1_magnitude, sensor2_magnitude, sensor3_magnitude, sensor4_magnitude, sensor1_theta, sensor2_theta, sensor3_theta, sensor4_theta,sensor1_phi,sensor2_phi,sensor3_phi,sensor4_phi;
void print_sensor_magnitudes(double (&sensor_values)[sensoren][werte]) {
  for (int i = 0; i < sensoren; i++) {
    double diff[werte];
    for (int j = 0; j < werte; j++) {
      diff[j] = sensor_values[i][j] - initial_sensor_values[i][j]; //initial_sensor_values is needed xD
    }
    double r,theta,phi;
    convertToSpherical(diff[0], diff[1], diff[2], r, theta, phi);
    piston_up[i][0] = r;
    piston_up[i][1] = theta;
    piston_up[i][2] = phi;
  }
}

void measure_initial_values() {
  calculate_average(initial_sensor_values);
}

bool compare(double piston_stuff[sensoren][werte])
{
  int hit_counter = 0;
  bool hit_detected = false;
  for (int i = 0; i < sensoren; i++) {
    double diff[werte];
    for (int j = 0; j < werte; j++) {
      diff[j] = piston_stuff[i][j]; //- initial_sensor_values[i][j];
    }
    double r,theta,phi;
    convertToSpherical(diff[0], diff[1], diff[2], r, theta, phi);
    piston_stuff[i][0] = r;
    piston_stuff[i][1] = theta;
    piston_stuff[i][2] = phi;
  }
  for (int i = 0; i < sensoren; i++) {
    double lower_bound = piston_up[i][0] * 0.875;
    double upper_bound = piston_up[i][0] * 1.125;
;
    if (piston_stuff[i][0] > upper_bound) {

      
      hit_counter++;
    } else if (piston_stuff[i][0] < lower_bound) {

      hit_counter++;
    } else {
       
    }
      
  }
  if (hit_counter>0)
  {
    hit_detected=true;
  }
  else
  {
    hit_detected=false;
  }
 return hit_detected;

}

bool compare_difference(double piston_stuff[sensoren][werte], double threshold)
{
  int hit_counter = 0;
  bool hit_detected = false;
  //int zahlen=0;
  for (int i = 0; i < sensoren; i++) {
    double diff[werte];
    for (int j = 0; j < werte; j++) {
      diff[j] = piston_stuff[i][j] - initial_sensor_values[i][j]; //ok initial_sensor_values[i][j] is needed xD
    }
    double r, theta, phi;
    Serial.println("vorconverttosperical");
    convertToSpherical(diff[0], diff[1], diff[2], r, theta, phi);
    Serial.println("nachconverttosperical");
    piston_stuff[i][0] = r;
    piston_stuff[i][1] = theta;
    piston_stuff[i][2] = phi;
    //zahlen++;
  }
 // Serial.println(zahlen);
  for (int i = 0; i < sensoren; i++) {
    double r_diff = abs(piston_stuff[i][0] - piston_up[i][0]);
    if (r_diff > threshold) {
      hit_counter++;
    }
  }
  if (hit_counter > 0) {
    hit_detected = true;
  } else {
    hit_detected = false;
  }
  return hit_detected;
}

void start_game()
{
   if(start_counting==false)
    {
      
      if(hammer_lift())  //if hammer is lifted
      {
        //start countdown
        for(int i=5; i>=0; i--)
        {
           showNumber(i);
           delay(1000);
        }
       
        startMillis = millis();
        gametime=15;
        start_counting=true;
      }
    
}
}

Game code: airpressure_sensor.hpp

Arduino
#include <Dps3xx.h>

// Dps3xx Object
Dps3xx Dps3xxPressureSensor = Dps3xx();
Dps3xx Dps3xxPressureSensor2 = Dps3xx();
float difference_dps_sensor=0;
bool game_begin=false;
uint8_t oversampling = 7;
float calc_difference();
float hight();
void init_dps_sensor()
{
  Dps3xxPressureSensor.begin(Wire1, 0x76);
  Dps3xxPressureSensor2.begin(Wire1);
  delay(1000);
  Serial.println("DPS Sensor Init complete!");
  difference_dps_sensor=calc_difference();
  Serial.println("Difference: ");
  Serial.print(difference_dps_sensor);
}

bool hammer_lift()
{
  bool logic=false;
  float hoehe=hight();
  if(game_begin==false)
  {
    if(hoehe>=30)
    {
    Serial.print("Hammer oben");
    game_begin=true;
    logic=true;
    }
    else
    {
    Serial.print("Hammer unten");
    }
  }
  else
  {
    game_begin=false;
  }
  return logic;
}

float calc_difference()
{//vielleicht hilft ein Filter
  float pressure_init_1=0;
  float pressure_init_1_filter=0;
  float pressure_init_2=0;
  float pressure_init_2_filter=0;
  int ret=0;
  float difference=0;
  for(int i=0; i<10;i++)
  {
    do
    {
      ret = Dps3xxPressureSensor.measurePressureOnce(pressure_init_1, oversampling);

      delay(50);
    }
    while(ret!=0);
    pressure_init_1_filter=pressure_init_1_filter+pressure_init_1;
  }

  pressure_init_1_filter=pressure_init_1_filter/10;
  for(int i=0; i<10;i++)
  {
    do
    {
      ret = Dps3xxPressureSensor2.measurePressureOnce(pressure_init_2, oversampling);

      delay(50);
    }
    while(ret!=0);
    pressure_init_2_filter=pressure_init_2_filter+pressure_init_2;

  }
  pressure_init_2_filter=pressure_init_2_filter/10;
  difference=pressure_init_2_filter-pressure_init_1_filter;

  return difference;
}

float hight()
{
  float pressure1;
  float pressure2;
  float heightDifference;
  
  int16_t ret;
  const float rho = 1.225; // kg/m (Luftdichte bei Standardbedingungen)
  const float g = 9.81; // m/s (Erdbeschleunigung)

  Serial.println();

 do
  {
    ret = Dps3xxPressureSensor.measurePressureOnce(pressure1, oversampling);
    Serial.print(ret);
  }
  while(ret!=0);

 do
  {
    ret = Dps3xxPressureSensor2.measurePressureOnce(pressure2, oversampling);
    Serial.print(ret);
  }
  while(ret!=0);

  heightDifference =abs((pressure1 - pressure2) / (rho * g) * 100)-abs(justus/ (rho * g) * 100); // in Zentimetern
  return heightDifference;
}

Game code: display.hpp

Arduino
//Display

#define segmentData 51
#define segmentClock 52
#define segmentLatch 50

#define dpa  1<<0
#define dpb  1<<6
#define dpc  1<<5
#define dpd  1<<4
#define dpe  1<<3
#define dpf  1<<1
#define dpg  1<<2
#define dpdp 1<<7

void init_display()
{
  Serial.println("Init Display begin");

  pinMode(segmentClock, OUTPUT);
  pinMode(segmentData, OUTPUT);
  pinMode(segmentLatch, OUTPUT);

  digitalWrite(segmentClock, LOW);
  digitalWrite(segmentData, LOW);
  digitalWrite(segmentLatch, LOW);

  Serial.println("Init Display finished");
}

void postNumber(byte number, boolean decimal)
{

  byte segments;

  switch (number)
  {
    case 1: segments = dpb | dpc; break;
    case 2: segments = dpa | dpb | dpd | dpe | dpg; break;
    case 3: segments = dpa | dpb | dpc | dpd | dpg; break;
    case 4: segments = dpf | dpg | dpb | dpc; break;
    case 5: segments = dpa | dpf | dpg | dpc | dpd; break;
    case 6: segments = dpa | dpf | dpg | dpe | dpc | dpd; break;
    case 7: segments = dpa | dpb | dpc; break;
    case 8: segments = dpa | dpb | dpc | dpd | dpe | dpf | dpg; break;
    case 9: segments = dpa | dpb | dpc | dpd | dpf | dpg; break;
    case 0: segments = dpa | dpb | dpc | dpd | dpe | dpf; break;
    case ' ': segments = 0; break;
    case 'c': segments = dpg | dpe | dpd; break;
    case '-': segments = dpg; break;
  }

  if (decimal) segments |= dpdp;

  //Clock these bits out to the drivers
  for (byte x = 0 ; x < 8 ; x++)
  {
    digitalWrite(segmentClock, LOW);
    digitalWrite(segmentData, segments & 1 << (7 - x));
    digitalWrite(segmentClock, HIGH); //Data transfers to the register on the rising edge of SRCK
  }
}



void showNumber(float value) //vielleicht kann dies auch ein INT sein. Ich muss dies mal testen
{
  int number = abs(value); //Remove negative signs and any decimals

  for (byte x = 0 ; x < 2 ; x++)
  {
    int remainder = number % 10;

    postNumber(remainder, false);

    number /= 10;
  }

  //Latch the current segment data
  digitalWrite(segmentLatch, LOW);
  digitalWrite(segmentLatch, HIGH); //Register moves storage register on the rising edge of RCK
}

//Given a number, or '-', shifts it out to the display

Game code: push.hpp

Arduino
#include <tle94112-ino.hpp>
#include <tle94112-motor-ino.hpp>
#include "SPI.h"

#define duration 20
Tle94112Ino controller = Tle94112Ino();

Tle94112Motor aktor1(controller);
Tle94112Motor aktor2(controller);
Tle94112Motor aktor3(controller);
Tle94112Motor aktor4(controller);
Tle94112Motor aktor5(controller);
Tle94112Motor aktor6(controller);
Tle94112Motor aktor7(controller);
Tle94112Motor aktor8(controller);
Tle94112Motor aktor9(controller);
Tle94112Motor kompressor(controller);

void init_mhb()
{
  controller.begin();
  
  aktor1.connect(aktor1.HIGHSIDE,controller.TLE_HB7);  //11
  aktor2.connect(aktor2.HIGHSIDE,controller.TLE_HB11); //8
  aktor3.connect(aktor3.HIGHSIDE,controller.TLE_HB10); //10
  aktor4.connect(aktor4.HIGHSIDE,controller.TLE_HB9);  //7
  aktor5.connect(aktor5.HIGHSIDE,controller.TLE_HB12);//9
  aktor6.connect(aktor6.HIGHSIDE,controller.TLE_HB8); //12
  aktor7.connect(aktor7.HIGHSIDE,controller.TLE_HB3);  
  aktor8.connect(aktor8.HIGHSIDE,controller.TLE_HB4);
  aktor9.connect(aktor9.HIGHSIDE,controller.TLE_HB6);
  kompressor.connect(kompressor.HIGHSIDE,controller.TLE_HB5);  
  kompressor.connect(kompressor.HIGHSIDE,controller.TLE_HB2);
  kompressor.connect(kompressor.HIGHSIDE,controller.TLE_HB1);

  aktor1.begin();
  aktor2.begin();
  aktor3.begin();
  aktor4.begin();
  aktor5.begin();
  aktor6.begin();
  aktor7.begin();
  aktor8.begin();
  aktor9.begin();
  kompressor.begin();
}

void push(int i)
{
  switch (i) 
    {
  //  hit_marker=0;
    case 1:    // your hand is on the sensor
       aktor1.start(255);
       delay(duration);
       calculate_average(piston_up);
       print_sensor_magnitudes(piston_up);
       aktor1.stop(0);  
      break;
    case 2:    // your hand is close to the sensor
       aktor2.start(255);
       delay(duration);
       calculate_average(piston_up);
       print_sensor_magnitudes(piston_up);
       aktor2.stop(0);  
      break;
    case 3:    // your hand is a few inches from the sensor
       aktor3.start(255);
       delay(duration);
       calculate_average(piston_up);
       print_sensor_magnitudes(piston_up);
       aktor3.stop(0);  
      break;
    case 4:    // your hand is nowhere near the sensor
       aktor4.start(255);
       delay(duration);
       calculate_average(piston_up);
       print_sensor_magnitudes(piston_up);
       aktor4.stop(0);  
      break;
    case 5:    // your hand is on the sensor
       aktor5.start(255);
       delay(duration);
       calculate_average(piston_up);
       print_sensor_magnitudes(piston_up);
       aktor5.stop(0);  
      break;
    case 6:    // your hand is close to the sensor
       aktor6.start(255);
       delay(duration);
       calculate_average(piston_up);
       print_sensor_magnitudes(piston_up);
       aktor6.stop(0);  
      break;
    case 7:    // your hand is a few inches from the sensor
       aktor7.start(255);
       delay(duration);
       calculate_average(piston_up);
       print_sensor_magnitudes(piston_up);
       aktor7.stop(0);  
      break;
    case 8:    // your hand is nowhere near the sensor
       aktor8.start(255);
       delay(duration);
       calculate_average(piston_up);
       print_sensor_magnitudes(piston_up);
       aktor8.stop(0);  
      break;
    case 9:    // your hand is nowhere near the sensor
       aktor9.start(255);
       delay(duration);
       calculate_average(piston_up);
       print_sensor_magnitudes(piston_up);
       aktor9.stop(0);  
      break;
    }
  
  //to see the value, if the piston is at the top :)

}

int random_generator()
{
  //if trust M works this code will be added here
  return random(1,9);
}

XMC-for-Arduino

Arduino core for the XMC microcontrollers.

3D Magnetic Sensor Arduino Library

Arduino library for Infineon's TLE493D 3D magnetic sensor series.

Arduino Library for Multi-Half-Bridge

Arduino library for Infineon's TLE94112ES Multi-Half-Bridge IC.

Arduino library for Digital Pressure Sensor

Arduino library for Infineon's DPS310 & DPS368 digital pressure sensors.

Credits

Infineon Team
100 projects • 157 followers
Contact

Comments

Please log in or sign up to comment.