2014-07-09 A mechanical solution to give the next prime number on button press

O.k. First the parts: the counter is a 24 volts one. Not so ideal. Makes a DC/DC-Step-Up converter necessary to create 24 volts. And a 7805 to supply the Attiny85.

Zero power. The NO switch turns on the DC/DC, the Attiny85 boots and its first thing is to switch on the relay to get power. Now the switch can be released.

Failed. The DC/DC wants some higher voltage than I planned to supply. So a DC/DC converter from 1.2V (lowermost end) to 5V, than 5V to 24V.

Failed. Turning on the second DC/DC draws so much energy, that the 5 volts break down and the relay releases. Due to attiny rebooting or whatever. So the second DC/DC will be turned on later by the Attiny.

This gives a relay for self holding and a 2N7000 for switching second DC/DC. Don’t ask.

For some reasons I can’t remember I found it useful that the Attiny can detect the state of the switch. Don’t ask, too.

Next obstacle: my Attiny85 development library chooses to erase the EEPROM while flashing the program code. So no way to synchronize the mechanical counter with the Attiny EEPROM. Until I found out all the things about fuses and such.

All the parts are glued into a Eduplay pirate treasure box. Sadly the counter is quite small.

A little bit of code lives inside the Attiny85:

Select
#include <EEPROM.h>
#include <EEPROMAnything.h>

/*
   Zaehler etc

 2014-06-27/28

 Zielplattform: attiny85

 */

const byte PinButtonsensor = A3;   // A3
const byte PinRelais = 4;          // D4
const byte PinDCDC = 1;            // D1      der Spannungswandler 5V->24V
const byte PinZaehler = 0;         // D0

unsigned long currentcounterdisplay;
unsigned long nextcounterdisplay;

//********************************************************************************************************************
//********************************************************************************************************************
void readEEPROMcurrentdisplay() {
  currentcounterdisplay=0;

  currentcounterdisplay = EEPROM.read(0);
  currentcounterdisplay += EEPROM.read(1)<<8;
  currentcounterdisplay += (unsigned long)EEPROM.read(2)<<16;
  currentcounterdisplay += (unsigned long)EEPROM.read(3)<<24;
}

//********************************************************************************************************************
//********************************************************************************************************************
void writeEEPROMcurrentdisplay() {

  EEPROM.write(0, currentcounterdisplay);
  EEPROM.write(1, currentcounterdisplay >> 8);
  EEPROM.write(2, currentcounterdisplay >> 16);
  EEPROM.write(3, currentcounterdisplay >> 24);
}


//********************************************************************************************************************
//********************************************************************************************************************
void setup() {
  pinMode(PinRelais, OUTPUT);
  digitalWrite(PinRelais,HIGH);

  // nix tun, damit sich alles laden kann
  delay(1000);

  // Z�hlerausgang setzen
  pinMode(PinZaehler,OUTPUT);
  digitalWrite(PinZaehler,LOW);
  
  // DCDC setzen
  pinMode(PinDCDC,OUTPUT);
  digitalWrite(PinDCDC,LOW);

  readEEPROMcurrentdisplay();
  // initialisieren des Displays bei Neubau etc.
  // currentcounterdisplay=327;
  
  // 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 
  // 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 
  // 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 
  // 349, 353, 359, 367, 373, 379, 383, 389,

  // n�chste Primzahl ausrechnen
  nextcounterdisplay=calcnextprime(currentcounterdisplay);

  // DCDC-Wandler an und etwas warten
  digitalWrite(PinDCDC,HIGH);
  delay(4000);
  // hochz�hlen
  runtonumber();

  // merken
  writeEEPROMcurrentdisplay();
  // und ausschalten
  turnoff();
}

//********************************************************************************************************************
//********************************************************************************************************************
void runtonumber (void) {

  while (nextcounterdisplay!=currentcounterdisplay) {
    digitalWrite(PinZaehler,HIGH);
    delay(200);
    digitalWrite(PinZaehler,LOW);
    delay(500);

    currentcounterdisplay++;
  }
}

//********************************************************************************************************************
//********************************************************************************************************************
boolean isprime(unsigned long number)
{
  unsigned long limit = sqrt(number)+1;

  // damit calcnextprime in einserschritten hochz�hlen kann. notwendig, wenn z�hler initialisiert werden muss
  if ((number % 2) ==0) {
    return false;
  }

  for (unsigned long i=3;i<limit;i=i+2) {
    if ((number % i)==0) {
      return false;
    }
  }
  return true;
}

//********************************************************************************************************************
//********************************************************************************************************************
unsigned long calcnextprime(unsigned long number) {
  number++;

  while (! isprime(number)) {
    number++;
  }

  return number;
}

//********************************************************************************************************************
//********************************************************************************************************************
void turnoff() {
  // relais off
  digitalWrite(PinRelais,LOW);

  // so lange der Knopf nicht gedr�ckt ist, k�nnen wir nicht ausgehen
  while (analogRead(PinButtonsensor)>100) {
    delay(1000);
  };
  // sind wir noch oder schon tot?
  delay(1000);
}


//********************************************************************************************************************
//********************************************************************************************************************
void loop() {
  // will this ever happen?
  delay(10000);
  turnoff();
}