Archive

Archive for the ‘arduino’ Category

reverse bits in a byte

July 25th, 2013 No comments

Working on a code for an arduino project I had the problem that the letters i had created for my 8×8 LED matrix were all mirrored. A letter looks like this:

byte letter_A[8] = { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00};

Now the rows are in the correct order (letter not upside down), but the leds of one row are wrong meaning the LSB should be the MSB. I found 3 solutions on the net which are all 3 cool in their own way:

The first version is a 1 to 1 translation of how i would do it on paper. Take the most left and swap it with the most right. Then take the second and swap it with the second last and so on …

// "00110011" becomes "11001100"
byte byteShift(byte num) {
  byte var = 0;     
  int i, x, y, p;
  int s = 8;    // number of bits in 'num'.
 
  for (i = 0; i < (s / 2); i++) {
    // extract bit on the left, from MSB
    p = s - i - 1;
    x = num & (1 << p);
    x = x >> p;  
    // extract bit on the right, from LSB
    y = num & (1 < < i);
    y = y >> i;
 
    var = var | (x < < i);       // apply x
    var = var | (y << p);       // apply y
  }
  return var;
}

The next version uses bit masks for reversing the order of bits

// Reverse the order of bits in a byte. 
// I.e. MSB is swapped with LSB, etc. 
byte Bit_Reverse( byte x ) 
{ 
    //          01010101  |         10101010
    x = ((x >> 1) & 0x55) | ((x < < 1) & 0xaa);
    //          00110011  |         11001100 
    x = ((x >> 2) & 0x33) | ((x < < 2) & 0xcc);
    //          00001111  |         11110000 
    x = ((x >> 4) & 0x0f) | ((x < < 4) & 0xf0); 
    return x;    
}

The last one is not pretty but pretty fast 😉

// 36 bytes small, inelegant assembler, but faster 
byte bitswap (byte x)
{
  byte result;
 
    asm("mov __tmp_reg__, %[in] \n\t"
      "lsl __tmp_reg__  \n\t"   /* shift out high bit to carry */
      "ror %[out] \n\t"  /* rotate carry __tmp_reg__to low bit (eventually) */
      "lsl __tmp_reg__  \n\t"   /* 2 */
      "ror %[out] \n\t"
      "lsl __tmp_reg__  \n\t"   /* 3 */
      "ror %[out] \n\t"
      "lsl __tmp_reg__  \n\t"   /* 4 */
      "ror %[out] \n\t"
 
      "lsl __tmp_reg__  \n\t"   /* 5 */
      "ror %[out] \n\t"
      "lsl __tmp_reg__  \n\t"   /* 6 */
      "ror %[out] \n\t"
      "lsl __tmp_reg__  \n\t"   /* 7 */
      "ror %[out] \n\t"
      "lsl __tmp_reg__  \n\t"   /* 8 */
      "ror %[out] \n\t"
      : [out] "=r" (result) : [in] "r" (x));
      return(result);
}

Categories: arduino Tags:

How to drive High Power LEDs

January 7th, 2012 3 comments

Well, I did it wrong last time 😉

From 28C3 Lightning Talks

Categories: arduino, nerdcore Tags: , , ,

Arduino Mega und libelium GPS

May 5th, 2010 No comments

Um den Ardiuno Mega mit dem libelium GPS Shield zu betreiben ist folgendes zu beachten:

Der Arduino Mega mit angeschlossenen libelium GPS Shield

  • Zusätzliches Netzteil wird benötigt (obwohl zum Beispiel in http://arduino.cc/blog/?p=243 nicht erwähnt).
  • Die RX/TX Ports 0/1 dürfen nicht verwendet werden, sondern die PWM 8/9 Ports über Software-Serial
  • Es empfiehlt sich den USB Port mit Isolierband ab zu kleben weil das GPS Shield evt. aufliegt

Beispielcode mit dem es bei mir funktioniert:

/*
 *  Copyright (C) 2008 Libelium Comunicaciones Distribuidas S.L.
 *  http://www.libelium.com
 *
 *  Copyright (C) 2010 Robin Geyer for nrtm.org
 *  http://www.nrtm.org/
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see .
 *
 *  Version 0.2-test
 *  Author: Marcos Yarza
 *  for nrtm.org: robin@pinguinstall.org
 */

#include <softwareserial.h>

/* define RX and TX pins on arduino (dont use 0/1 it doesnt work) */
#define rxPin 9
#define txPin 8

/* set up the serial port for on-arduino-board communication with gps-shield*/
SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);

/* variables */
byte byteGPS = 0;
int i = 0;
int k = 0;
int isgsv = 0;
int conf = 0;

/* buffer for NMEA sequences */
char inBuffer[300] = "";

/* arduino setup routine */
void setup(){

  /* setup for internal UART port */
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
  mySerial.begin(4800);

  /* setup for external Serial port (e.g. USB connection)*/
  Serial.begin(19200);

  /* setup the GPS module */
  Serial.println("Configure GPS...");
  delay(1000);

  /* tell the gps module the 4800 baud connection */
  mySerial.println("$PSTMNMEACONFIG,0,4800,1,1");
  delay(500);

  /* command for setting time and position, just to give the module a hint (location saxonia) */
  mySerial.println("$PSTMINITGPS,5200.000,N,01300.000,E,0197,01,06,2010,12,00,00");
}

/* arduino base loop */
void loop(){
  /* switch between the different NMEA outputs */
  switch (conf){
  case 0:
    mySerial.println("$PSTMNMEACONFIG,0,4800,1,1");        /* show only GGA */
    conf = 1;
    isgsv = 0;
    break;
  case 1:
    mySerial.println("$PSTMNMEACONFIG,0,4800,4,1");        /* show only GSA */
    conf = 2;
    isgsv = 0;
    break;
  case 2:
    mySerial.println("$PSTMNMEACONFIG,0,4800,8,1");        /* show only GSV */
    conf = 0;
    isgsv = 1;
    break;
  default:
    mySerial.println("$PSTMNMEACONFIG,0,4800,1,1");        /* show only GGA */
    isgsv = 0;
  }
  delay(500);

  byteGPS = 0;
  i = 0;

  /* all sequences */
  while(byteGPS != 42){
    byteGPS = mySerial.read();
    inBuffer[i]=byteGPS;
    i++;
  }

  k = 1;
  while(inBuffer[k] != 42){
    Serial.print(inBuffer[k]);
    k++;
  }

  /* only if its a GSV Sequence */
  if (isgsv == 1) {
    byteGPS = 0;

    Serial.println();
    while(byteGPS != 42){
      byteGPS = mySerial.read();
      inBuffer[i]=byteGPS;
      i++;
    }

    //k = 1;
    while(inBuffer[k] != 42){
      Serial.print(inBuffer[k]);
      k++;
    }
    Serial.println();
    byteGPS = 0;

    while(byteGPS != 42){
      byteGPS = mySerial.read();
      inBuffer[i]=byteGPS;
      i++;
    }

    // k = 1;
    while(inBuffer[k] != 42){
      Serial.print(inBuffer[k]);
      k++;
    }
  }
  /* GSV Only END */

  Serial.println();
  delay(1000);
}

Liefert abwechselnd den Output (GSV funktioniert noch nicht richtig, da ist noch etwas Debugging nötig):

GPGGA,191651.000,5102.607,N,01347.778,E,2,06,3.9,0117.6,M,45.7,M,,
GPGSA,A,3,26,09,12,27,30,14,,,,,,,6.2,3.9,4.9
GPGSV,3,1,11,26,13,191,30,09,46,141,44,12,83,320,31,27,41,142,43

GPGGA,191700.000,5102.605,N,01347.778,E,2,06,3.9,0118.4,M,45.7,M,,
GPGSA,A,3,26,09,12,27,30,14,,,,,,,6.2,3.9,4.9
GPGSV,3,1,11,26,13,191,32,09,46,141,44,12,83,320,36,27,41,142,43

Wobei die NMEA Sequenzen hier erklärt sind:

http://www.kowoma.de/gps/zusatzerklaerungen/NMEA.htm

Categories: arduino Tags: , ,