Steeph's Web Site

Menu

Entries tagged 'cat:DIY'

PIN Changer

I had to change the default PINs of over 200 SIM cards once. And such a situation could arise again. So I've built a PIN changer in which I just have to insert the card, wait a few seconds and it's done.

The Card Slots

SIM cards in their natural form factor aren't as fiddly to handle as they are in the form factors most people know, which is Mini SIM, Micro SIM and Nano SIM. Classical SIM cards are the same size as other smart cards. I found a card slot with an end switch on eBay. I like it when I find industry grade parts for cheap on eBay as part of some remaining stock. Additionally I've used a slide-in mini SIM slot and another, separate end switch from my parts collection in case I to change the PINs of smaller cards.

The Baseband Processor

Other parts that I've used is an Arduino Nano sized Arduino Nano nearly-clone and an A6 modem module. There are many similar modem modules designed around different but similar ICs. Many of them are cheap and widely used for DIY IoT projects. So example code for the Arduino and other help can be easily found on the web. I don't know why I went with a module with an A6. But it works fine and there are an Arduino library for it as well as cheap modem modules with it available.

(tba:voltage supply)

The Controller

Yes, Arduino may be kind of the noob go-to board and could look up how to use microcontrollers on their own finally and even if I don't want to I could finally start to use ESP32s like everybody else. But I know Arduinos and by now I'm familiar with it and it works, so, whatever. Arduino Nano is kind of my go-to form factor now because they have integraded USB, are Uno compatible and small. Unless I need more or something very specific I use Arduino Nano almost-clones with USB-C port.

The Code

The code is a real mess. It had been a long time since I had written any even halfway serious C. It may have been the first time, actually. The sketch surely is very easily improved by somebody who knows what they are doing. I intended to improve it myself. But the project is currently abandoned and The code is doing what it should in a way I initially had in mind as the goal. But I'll leave the mess of the comments in for the case that somebody wants to make out what I was thinking.


// Funktionen umschreiben: Beim Empfangen wird erwartet: 1. der AT-Command zurück, 2. eine Antwort, 3. OK oder ein ERROR.
//                         Daher sollte abgefragt werden, bis entweder OK oder ERROR kam oder 20/50/9001(?) Abfragen lang weder OK noch ERROR an kam.
//                         Die Antwort in Variable speichern? Naja, String zurückgeben halt.
//                         Antworten, die mit "^" anfangen brauchen nicht gehandlet zu werden, da keine Kommandos, die mit AT^ beginnen gesendet werden.


#include  

SoftwareSerial A6MODULE(6,7);
int intled = 13; // Internal LED
int successled = 8; // Green LED
int failled = 9; // Red LED
int wrongpinled = 10; // Orange LED

boolean debug=true;

//String commands[5] = { "AT", "AT+CPINC2", "AT+CPIN?", "AT+CLCK=\"SC\",2", "AT+CPIN=\"3010\"" };
//int command = 0;

const byte maxmsglength = 32;
char received[maxmsglength];
boolean newData = false;
String response = "";

int i=0;

/*
To check/do:
1  AT: OK?
2  is PUK required - abort
3  are less than 3 PIN attempts left? - abort AT^CPINC=?
4  is PIN disabled
       5  enable it: 0000
6  is PIN enabled
       7  unlock
8  is card unlocked
       9  change PIN: 1996
              was PIN wrong - report and leave it
*/


void setup() {
  pinMode(intled, OUTPUT);
  pinMode(successled, OUTPUT);
  pinMode(failled, OUTPUT);
  pinMode(wrongpinled, OUTPUT);
  // All LEDs turn on at the beginning and stay on during the wait period at the beginning, then turn off before communication with the A6 module starts.
  digitalWrite(intled, HIGH);
  digitalWrite(successled, HIGH);
  digitalWrite(failled, HIGH);
  digitalWrite(wrongpinled, HIGH);
  Serial.begin(9600);
  delay(500);
  digitalWrite(intled, LOW);
  digitalWrite(successled, LOW);
  digitalWrite(failled, LOW);
  digitalWrite(wrongpinled, LOW);
  A6MODULE.begin(9600);
  delay(500);
  digitalWrite(intled, LOW);
}

void loop() {
  sendtoa6("AT");
  if(getfroma6("OK")) {
//    sendtoa6("AT+CPIN?");
//    if(getfroma6("+CPIN:SIM PUK")) { fail; }         // If the required password is PUK, abort.
//    sendtoa6("AT+CPIN?");
//    if(getfroma6("+CPIN:SIM PIN2")) { fail; }        // If the required password is PIN2, abort.
//    sendtoa6("AT+CPIN?");
//    if(getfroma6("+CPIN:SIM PUK2")) { fail; }        // If the required password is PUK2, abort.

// WAIT FOR SWITCH RELEASE FIRST
    sendtoa6("AT+CPIN?");
    getfroma6("+CPIN:SIM PIN");                      // The last non-empty response will be stored in the global response variable. Problem with this: If the A6 module sends an unsolicitated message before the response to the CPIN command, nothing gets done and the card needs to be re-inserted again.
    if(strcmp(response, "OK") == 0) {                // If already no PIN is required

//      sendtoa6("AT+CLCK=\"SC\",2"); // Ist PIN-Abfrage eingeschaltet? Oder ist es "SC"?
//      if(getfroma6(???)) { PIN-Abfrage einschalten mit 0000; }

      // ENABLE PIN HERE
      d("I don't know how to enable the PIN.");

    }
    if(response = "+CPIN:SIM PIN") {                 // If the required password is PIN, continue.
      sendtoa6("AT^CPINC=?");
      if(getfroma6("^CPINC: 3")) {                   // If not exactly 3 attempts are left, abort. (should be larger than or equal to 3, shouldn't it?)
        sendtoa6("AT+CPIN=\"0000\"");                // Freischalten mit 0000
        delay(50);
        if(!getfroma6("OK")) { fail; }               // If that was not the right password, abort.
        sendtoa6("AT+CPWD=\"SC\",\"0000\",\"1996\"");// PIN ändern
        delay(500);
        if(getfroma6("OK")) { Serial.println("Looking good."); }

//      sendtoa6("AT+CMGD=0,4"); // Should delete all SMS
//      if(getfroma6(???)) { ; }
        d("I don't know how to delete SMS.");

        sendtoa6("AT+CPIN?");
        if(getfroma6("+CPIN:READY")) {
          
          // TURN OFF A& MODULE FOR SAFE CARD REMOVAL

          digitalWrite(successled, HIGH);
        }
      } else {                                         // If not exactly 3 times left
        fail;
      }
      delay(1000);
    }
  }
}

void fail() {
  digitalWrite(failled, HIGH);               // Turn red fail LED on and ...
  d("Something failed! Ending programme.");
  while(1);                                  // ... don't do anything anymore.
}

void wrongpin() {
  digitalWrite(wrongpinled, HIGH);           // Turn yellow LED on and ...
  d("Wrong PIN! Ending programme.");
  while(1);                                  // ... don't do anything anymore.
}

//boolean getfroma6(char str[32], char str1[32], char str1[32], char str1[32], char str1[32], char str1[32]) { // Returns true if the passed (expected) message was received, false if anything else was received.
boolean getfroma6(char str[32]) { // Returns true if the passed (expected) message was received, false if anything else was received.
  boolean asexpected = false;
    for (i = 1; i < 9; ++i) {
    receivelinefroma6();
//    d("d1 "+response);

    if(received[0] == '\0') {                            // If the received message is empty
      continue;
    } else {
      response = received;
    }
    if(strstr(received, "ERROR") != NULL) {              // If the received message contains "ERROR"
      d("Received an error: "+response);
      fail;
    }
    if(received[0] == '+') {                             // If the received message starts with a "+" sign
      d("Reseived response: "+response);
    } else {
      if(strstr(received, "OK") != NULL) {               // If the received message is "OK"
        d("Received OK.");
        asexpected = true;                               // Also treat OK like the expected message. No unexpected OK should ever be sent from the A6 module. So this is fine. No, it is, really.
//        if(asexpected) { return true; }
      } else {
        if(strncmp(received,"AT",2) == 0) {              // If the received message starts with "AT"
          d("Received AT: "+response);
        } else {                                         // For any other received message
          d("Received: "+response);
        }
      }
    }
    newData = false;
    if(strstr(received, str) != NULL) {
      d("Received expected message: "+response);
      asexpected = true;
    }
  }
  if(asexpected) { return true; }
  return false;
}


//void handleresponse() {
//  response = received;
//  if(received[0] == '+') {
//    d("               Response: "+response);
//  } else {
//    if(strstr(received, "OK") != NULL) {
//      d("               It's okay.");
//    } else {
//      if(strncmp(received,"AT",2) == 0) {
//        d("               I've sent: "+response);
//      }
//    }
//  }
//  newData = false;
//}



void receivelinefroma6() {
  delay(80);
  static byte counter = 0;
  char rc;
  
  received[0] = '\0';

  while (A6MODULE.available() > 0 && newData == false) {
    rc = A6MODULE.read();

    if (rc != '\n') {
      received[counter] = rc;
      counter++;
      if (counter >= maxmsglength) {
          counter = maxmsglength - 1;
      }
    }
    else {
      received[counter] = '\0'; // terminate the string
      counter = 0;
      newData = true;
    }
  }
}

void sendtoa6(String command) {
//  Serial.println(command);
  A6MODULE.println(command);
  d("Sent: "+command);
}

void d(String line) {
  if (debug == true) { Serial.println(line); }
}

(tba:connections,assembly,photos?)

USB/Serial PWM Fan Controller Using an Arduino

I wanted to be able to control the speed of the fans in my big NAS, Fred, individually. Even though the mainboard in use has five PWM fan connectors, the chipset can only control the speed of all fans together. There are probably good fan controllers commercially available that solve this problem better than I did. But they seemed overpriced and it seemed like a fun learning project for me.

The fan controller that I made uses an Arduino Nano clone that listens to it's serial port, waiting for a command to change the speed of a fan. When a command is recognised the continuous PWM signal for that fan is changed accordingly. It's possible to control up to six fans this way with an Arduino Nano. I'm only using three though since I only have three fan groups that need to be controlled separately.

The Arduino sketch/C code for the Arduino Nano that I used is as follows.




//fan speed sensor wire attached to digital pin 2 with a 10kohm pullup resistor
//fan PWM control wire attached directly to digital pin 9

#include <PWM.h> //include PWM library http://forum.arduino.cc/index.php?topic=117425.0

volatile int half_revolutions1; //allow half_revolutioins to be accesed in intterupt
volatile int half_revolutions2; //allow half_revolutioins to be accesed in intterupt
int rpm1; //set rpm as an integer
int rpm2; //set rpm as an integer
int pwm=255;
const byte numChars = 5;
char receivedChars[numChars];

boolean newData = false;

void setup()
{
  InitTimersSafe(); //not sure what this is for, but I think i need it for PWM control?
  bool success = SetPinFrequencySafe(9, 25000); //set frequency to 25kHz
  pwmWrite(9, 51); // 51=20% duty cycle, 255=100% duty cycle

  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  analogWrite(5, 170);
  analogWrite(6, 255);
  pinMode(2,INPUT_PULLUP); //set RPM pin to digital input
  pinMode(3,INPUT_PULLUP); //set RPM pin to digital input
  half_revolutions1 = 0;
  rpm1 = 0;
  half_revolutions2 = 0;
  rpm2 = 0;

  Serial.begin(9600);
}



void loop()
{
  sei(); //enable intterupts
  attachInterrupt(0, fan_rpm1, RISING); //record pulses as they rise
  delay(1000);
  detachInterrupt(0);
  attachInterrupt(1, fan_rpm2, RISING); //record pulses as they rise
  delay(1000);
  detachInterrupt(1);
  cli(); //disable intterupts

  rpm1 = (half_revolutions1/2)*60;

  Serial.print("1");
  Serial.println(rpm1);

  rpm2 = (half_revolutions2/2)*60;

  Serial.print("2");
  Serial.println(rpm2);

  rpm1 = 0;
  half_revolutions1 = 0;

  rpm2 = 0;
  half_revolutions2 = 0;

  pwm = 255;
  recvWithStartEndMarkers();
  processCommand();
}

void fan_rpm1()
{
  ++half_revolutions1; //increment before returning value
}


void fan_rpm2()
{
  ++half_revolutions2; //increment before returning value
}


void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = 's';
    char endMarker = '\n';
    char rc;
 
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void processCommand() {
    if (newData == true) {
        Serial.print("s");
        Serial.println(receivedChars);
        switch (receivedChars[0])
        {
            case '1':
                receivedChars[0] = '0';
                sscanf(receivedChars, "%d", &pwm);
                analogWrite(5, pwm);
                break;
            case '2':
                receivedChars[0] = '0';
                sscanf(receivedChars, "%d", &pwm);
                analogWrite(6, pwm);
                break;
            case '3':
                receivedChars[0] = '0';
                sscanf(receivedChars, "%d", &pwm);
                
                break;
//            default:
//                Serial.println("I don't know what that means.");
        }
        newData = false;
    }
}

Well, how should I put it? It works, usually.

(tbc?)

(tba:photos)

Project Idea And A Little Story: High Power PC Cooled Completely Passively With Heat Pipes And A Large Surface Aluminium Case And My First Online Post Ever

Here is another project idea that I'll probably never realise. It's not really an ingenious idea or a new concept. But there is a reason for why I can't forget about it.

In the very early 2000s, when I started to tinker with PC cases and also made my first steps in web communities, I thought about how I could reduce the noise my computers made without running chips at dangurously hight temperatures or forgoing performance. I've read about heat pipes in some case modding community. And I thought why not take it to the extreme to move heat quickly not just to a larger heat sink than the CPU sockets could safely hold (Motherboards didn't have cooler brackets back then.) but to a heat sink or several heat sinks that cover the majority of the case's surface. When the first commercial CPU coolers with heat pipes came on the market, targetet at computer tinkerers, but still nobody in the community seemed to attempt to make a case with a huge heat sink on the outside of the wall to cool even a 2 GHz Pentium 4 with its 75 Watts TDP passively, I decided to register in a small case modding web forum and present my idea to see what might be wrong with the concept. I was actually younger 20 years ago than I am now and I had never before tried to get myself out there in such a way. I thought it was a rather good idea. But I wasn't sure how much surface and aluminium mass I needed and wether it was realistic to cool a powerful CPU passively that way. Trying to cool a Pentium 4 only passively sounds like a stupid idea after all.

So I created a post on said web forum that I've never read before, presented my idea and asked for opinions. I got a few answers and everybody seemed to think it was a stupid idea. One respondant didn't seem to get my idea but still seemed to think it was stupid. One person seemed rather friendly in comparison and asked if I could explain the idea in more detail. I felt bullied by the negative answers, I felt mocked by being inline quoted (which I don't think I had seen before) and I felt that my ideas were generally worthless since I wasn't one of those hobbyistic experts that actually know stuff and are able to answer questions asked in a web forum. So rather than explaining my idea in more detail as requested, I searched for a way to delete my post, didn't find one and asked in the same thread how I could remove it.

I didn't find the post when i searched for it a few years ago. Like most small web forums it has probably gone offline with nothing or almost nothing in a web archive. But with the experiece that I have today I suspect that I didn't explain my idea very well and the other forum members didn't realise that I was a very insecure child. I also realised many years later that it wasn't a bad idea. I even saw a computer case that implemented the same idea being sold at some point. I don't know if many people bought this. But at least somebody other than me seemed to think it made sense and could even be commercialised. This redeemed my idea in my mind and I started to think about making such a case again. But I don't have the need for high-power CPUs and didn't want to invest money into another project that I wouldn't ever finish once the initial exitement would be over by buying huge heat sinks and heat pipes. So I've added it to that huge imaginary list with projects that I like to would have done but likely wouldn't finish and conclude my decades long considerations and my decision to conclude them by writing this entry.

Done.

Fred (The Case Lid And Cooling)

This entry is a reply to or continuation of the entry 'Fred (Power Supplies)'.

In this entry I'll describe how Fred's components are air cooled.

So, after removing the fan wall and unplugging the two fans in the back of the case there was no active cooling left. That's good for reducing noise, but not enough cooling for the hard drives, the CPU and the SAS controller cards. Since the case is not mounted in a rack and nothing is placed on top of it, I decided to use the space in the case lid to place larger fans.

The CPU

My idea was to replace the CPU cooler with a larger one that just fits into the case and have a fan above it suck out its hot air (also pulling in ait from the RAM modules next to the CPU socket). I fount a heat sink from Scythe called Iori (SCIOR-1000). Mounted on the socket there would be just enough space for a 15 mm fan above it. As it turns out though, the heat sink is large enough to cool the CPU passively and the RAM doesn't need any additional cooling, too. So the fan above it is not even plugged in.

The Extension Cards

Since the HBA and the RAID card that I'm using are designed for servers with a proper airflow, they need at least some additional cooling. Their heat sinks are quite small for the amount of heat they produce. But there was enough room above them to place a fan that sucks the hot ait directly from the extension card area out of the case. I was told these cards usually don't have any problems getting extremely hot. But I rather don't want to have them do their things for hours or days streight without any active cooling. Replacing their heat sinks with larger ones would only be a sufficiant option if there was room for much much larger heat sinks.

The Hard Drives

I don't want to have have hard drives run continuesly without any active cooling, especially when they are sitting in enclosures that don't allow for any aitflow without some amount of pressure. There is just no-where for the heat to go on its own in these tight drawers. I decided for three 140 mm fans that would neatly in a row behind the hard drive compartment and backplane. Since the motherboard isn't that large, there was nothing but a few cables in that area of the case. I've mounted an aluminium bar that I had lying around and tucked two pieces of flat plastic between this bar and the bar that originally held the fan wall at the bottom. That way, the air that is pressed in from above gets directed only into the hard drive compartment where it has no way to escape without passing the hard drives.

Unfortunately the room around the hard drives is so small that quite a lot of air preassure is needed to cool them as much as I wanted to. Running the fans at full speed all the time is hardly enough to keep them at a temperature that I deem acceptable. I tried to increase the cooling effect by sealing all the edges and other tiny spaces where some air could escape without cooling the hard drives. But this didn't lead to a measurable difference. I ended up taking out two of the 16 hard drives to increase the size of the duct. I chose two drives in the centre so that there now is a large surface where the air cools the remaining drives. That lowered the temperatures of the surrounding drives a lot. The temperature of the drives at the edges was of course hardly effected. But those weren't the problem anyway.

I'll probably continue about the rest of the case mod in a followup entry.

Fred (Power Supplies)

This entry is a reply to or continuation of the entry 'Fred (Modding The Quiet Into A Server Rack Case)'.

After getting rid of the fan wall, the power supply was the main source of noise. The original PSU was a 3U redundant (2+1) server power supply. Noise does not matter with machines like that. I wanted to be able to have it running in my living room though, so the noise had to drop a fucking lot. Seriously, that's said so many times for people who don't work with servers like this. But people are still surprised when they hear a server fan for the first time. One of original 60 mm fans in the back is louder than my vaccum cleaner. And there were two of those, four 80 mm fans and five 40 mm fans. Three of the latter in the power supplies. Because I have no means to control the fans in software and don't need all the power the power supply can supply, I tried how much I can lower the noise by adding resistors in series to the fans. That did reduce noise a lot. But not only aren't these fans optimated for quiet operation, they are 40 mm fans. They will nver be quiet enough.

So I looked online for a power supply that (1) fits in the case (it's not completely ATX), (2) can supply enough curret for everything and (3) is trustworthy/doesn't appear to be too cheap. I found a Newton Power Model NPS-300AB B, which doesn't meat points 2 and 3 but fits perfectly into the case that it was a weird feeling to accept that it is mostly coincidence. I only had to drill the screw holes and that was it. It's hardly wnough for 14 HDDs and the internet sais it's really cheap and not trustworthy. But I went with it anyway in order to pay tribute to r/thingsfittinginthings.

Not a year later the PSU died and was replaced by a better SFX unit.

About the rest of the mod in separate entries.