Jump to content
43oh

msp430 peripherals to tm4C123G peripherials


Recommended Posts

I found an adaptation of a cap-sense sketch that uses port manipulation to create a capacitive sensor for Arduino to a MSP430. My question is that when I was using the sketch and adjusting it to use a tm4C123 device, I got these errors:

 

TouchSensor.ino: In function 'uint8_t readCapacitivePin(int)':
TouchSensor.ino:58:24: error: 'P1OUT' was not declared in this scope
TouchSensor.ino:59:23: error: 'P1DIR' was not declared in this scope
TouchSensor.ino:61:23: error: 'P1IN' was not declared in this scope
 
I looked into this and found out on this post:
 
That this is using peripheral names on the MSP430 regarding registers

P1DIR - to set direction
P1OUT - to set an output bit

P1IN - to read an input bit

I remembered that wiring.c defined the port, pin and ddr. And if I commented out

 
    port = (uint8_t*) &P1OUT;
    ddr = (uint8_t*) &P1DIR;
    bitmask = 1 << pinToMeasure;
    pin = (uint8_t*) &P1IN;

It would compile but I feel I am missing something

 

My problem is that I was looking into how to change the peripheral names for tm4c123 instead of the MSP430 so I can use the sketch on my tm4c123.

 

Here is the link to the sketch:

https://gist.github.com/thecodemaiden/6040927

 

Link to post
Share on other sites

You need to translate the function of those special register references.

If you look in the MSP430 wiring.c you may see how those special registers are used on the MSP430.

Compare that to wiring.c for the Tiva LP, and you may be able to translate it to equivalent Tiva macros.

(Which might give you a shortcut, vs. reading the MSP430 data sheet to understand what the registers do,

then reading the Tiva data sheet to come up with equivalent calls.)

 

Pretty much the same suggestions as I gave in this thread

http://forum.stellarisiti.com/topic/2150-tm4c123g-arduino-library-problem/

 

Did that other capacitive library not work for you?

 

Be aware that some MSP430 have special capacitive sense pins.  Not sure if this library uses those pins, and whether that is just a hardware thing, or if the software for an MSP430 cap sense is different than would use for devices without the special function.

 

You might also look at the capsense demo which is part of Tivaware.

Link to post
Share on other sites

Hi,

Thanks for replying. About the other capacitive library, I am still working on it but I found this example as there is no external libraries to use and only port manipulation on the sketch to read a capacitive sensor (or voltage) reading. Also I can save up pin usage if I can complete this example. This example actually will help me understand more about how port registers  and port manipulation to a degree, work between Arduino/other microcontrollers and my TM4C123G.

 

Back to the topic, I assume that the many of the pins I have on the TM4C123G are capable of capacitive sensing. Here was an example someone did of what I am trying to attempt with only a TM4C123G:

 

http://hackaventure.blogspot.com/2013/12/capacitive-touch-sensing-using-arm.html

 

He only used one GPIO to read the timing of the charging and discharging of the sensor and the example I posted on this topic is very similar process.

 

After comparing the wiring.c for each the MSP430 and TM4C123G, I think that the special functions only relate to pinMode, digitalRead and digitalWrite. I writing this as my first attempt:

uint8_t readCapacitivePin(int pinToMeasure){
  // This is how you declare a variable which
  //  will hold the PORT, PIN, and DDR registers
  //  on an AVR
  
  volatile uint8_t* port; //use digitalWrite
  volatile uint8_t* ddr; //use pinMode
  volatile uint8_t* pin; //use digitalRead
  // Here we translate the input pin number from
  //  Arduino pin number to the AVR PORT, PIN, DDR,
  //  and which bit of those registers we care about.
  byte bitmask;
 
  // port = (uint8_t*) &P1OUT;
  // ddr = (uint8_t*) &P1DIR;
  // bitmask = 1 << pinToMeasure;
  // pin = (uint8_t*) &P1IN;

  port = digitalPinToPort(pinToMeasure);
  bitmask = digitalPinToBitMask(pinToMeasure);

When I verified this on Energia, I get these kinds of errors:

error: invalid conversion from 'uint8_t {aka unsigned char}' to 'volatile uint8_t* {aka volatile unsigned char*}' [-fpermissive]

I checked that volatile uint8_t* ... is a type of array and that is how the all of the pins are called I believe and finding the ones that are used.

 

My issue is should I have to remove the volatile uint8_t *... from the program or should I continue looking at the wiring.c for the MSP430 and TM4C123G to figure out the macros? What is it I am not getting would sum up my problems so far. It is tedious and I have looked at it for hours with not much success.

Link to post
Share on other sites
port = digitalPinToPort(pinToMeasure);

This is on the right track - just haven't gone far enough with it.  (digitalPinToPort returns a port number, and you want a register address).

Looking in Energia.h , portDATARegister looks like a likely candidate (takes a port number, returns a pointer to volatile uint8_t

Checking in the chip documentation (tm4c123gh6pm.pdf) it says the DATA register is what we want for reading or writing.

port = portDATARegister(digitalPinToPort(pinToMeasure));

This ought to work.

 

(I sort of glossed over some nice extra features there.  If one wishes to pursue it, one could take better advantage of the Tiva port hardware by using the same macros as in the other thread http://forum.stellarisiti.com/topic/2150-tm4c123g-arduino-library-problem/#entry7999

 

Likewise, note the macro portDIRRegister(P), documentation says clear a bit there for input, set bit to make that pin output.  Looks helpful for ddr.

Link to post
Share on other sites

An aside - you didn't mention which version of Energia you are using.  In Energia 13 there is an error in the 

Delay functions (delay, delayMicroseconds, sleep, sleepSeconds) See
http://forum.43oh.com/topic/5902-measure-short-amounts-of-time-with-micros/

 

So the delay(1) in code you are using may not work correctly.

Easy fix is to use previous version of Energia.

 

[Edit: Ignore this, does not apply.]

Link to post
Share on other sites

Okay, Thank you for your help on this igor.

 

I looked at the references at Energia.h for the lm4f cores and I believe for the pin register, I would use the portBASERegister for this.

I do have some concerns. I found out that reason I got the error regarding the volatile uint8_t was because the example was using 

volatile uint8_t* port;
volatile uint8_t* ddr; 
volatile uint8_t* pin;

uint8_t values in the energia.h for MSP430. The energia.h for the ports uses uint32_t values instead so I changed them to use uint32_t:

uint8_t readCapacitivePin(int pinToMeasure){
  // This is how you declare a variable which
  //  will hold the PORT, PIN, and DDR registers
  //  on an AVR
  
  volatile uint32_t* port; //use digitalWrite
  volatile uint32_t* ddr; //use pinMode
  volatile uint32_t* pin; //use digitalRead
  // Here we translate the input pin number from
  //  Arduino pin number to the AVR PORT, PIN, DDR,
  //  and which bit of those registers we care about.
  byte bitmask;
 
  // port = (uint8_t*) &P1OUT;
  // ddr = (uint8_t*) &P1DIR;
  //bitmask = 1 << pinToMeasure;
  // pin = (uint8_t*) &P1IN;

  port = portDATARegister(digitalPinToPort(pinToMeasure));
  ddr = portDIRRegister(digitalPinToPort(pinToMeasure));
  bitmask = 1 << pinToMeasure;
  pin =  portBASERegister(digitalPinToPort(pinToMeasure));
  

It now compiles without errors but I was wondering about that should I be concerned about the conversion from uint8_t to uint32_t, that will it may cause problems when I test it out on the TM4C123G? All I know is that it is calling unsigned integer of length of 8 bits and now I am calling unsigned integer of 32 bits (this is the first time I am using uint8_t and uint32_t).

 

Also I think bitmask should be the same as from http://arduino.cc/en/Tutorial/BitMask, all it does is that access specific bits.

If I am missing something or got something wrong, please tell me.

Link to post
Share on other sites

Almost - except for pin, which should be the same as port (i.e. on Tiva you can use the same register for reading or writing a port bit.)

The uin32_t should not cause problems (actually since the ports are 8 bits on Stellaris, one might be able to get by with uint8_t, I don't know which would give the best code).  

Link to post
Share on other sites

Okay, after I tested this code on my tmc123g, I ran into a bad problem. When I compiled and uploaded the code, the serial monitor tells me that value of the capacitance is 128 but my main issue is that the LED lights up before I even touch my sensor. Most likely, the timing and cycles are not  After looking and testing around what caused my error, I believe that the port manipulation is causing the pin to charge up be high and may not be discharging but again I cannot say for sure.

 

I may be wrong but looking at the readCapacitivePin function I cannot make any progress on this.

// Pin for the LED
#define redLED RED_LED
// Pin to connect to your drawing
int button1N = 4;
int button2N = 5;
// This is how high the sensor needs to read in order
//  to trigger a touch.  You'll find this number
//  by trial and error, or you could take readings at 
//  the start of the program to dynamically calculate this.
int touchedCutoff = 60;
 
#include <Energia.h>

void setup(){
  Serial.begin(9600);
  // Set up the LED
  pinMode(redLED, OUTPUT);
  digitalWrite(redLED, LOW);
}
 
void loop(){
  // If the capacitive sensor reads above a certain threshold,
  //  turn on the LED
  if (readCapacitivePin(button1N) > touchedCutoff) {
    digitalWrite(redLED, HIGH);
  }
  else {
    digitalWrite(redLED, LOW);
  }
 
  // Every 500 ms, print the value of the capacitive sensor
  if ( (millis() % 500) == 0){
    Serial.print("Capacitive Sensor on Pin 4 reads: ");
    Serial.println(readCapacitivePin(button1N));
  }
}
 
// readCapacitivePin
//  Input: x in P1.x pin name 
//  Output: A number, from 0 to 17 expressing
//          how much capacitance is on the pin
//  When you touch the pin, or whatever you have
//  attached to it, the number will get higher
//  In order for this to work now,
// The pin should have a 1+Megaohm resistor pulling
//  it up to +5v.
uint8_t readCapacitivePin(int pinToMeasure){
  // This is how you declare a variable which
  //  will hold the PORT, PIN, and DDR registers
  //  on an AVR
  
  volatile uint32_t* port; //use digitalWrite
  volatile uint32_t* ddr; //use pinMode
  volatile uint32_t* pin; //use digitalRead
  // Here we translate the input pin number from
  //  Arduino pin number to the AVR PORT, PIN, DDR,
  //  and which bit of those registers we care about.
  byte bitmask;
 
  // port = (uint8_t*) &P1OUT;
  // ddr = (uint8_t*) &P1DIR;
  //bitmask = 1 << pinToMeasure;
  // pin = (uint8_t*) &P1IN;

  port = portDATARegister(digitalPinToPort(pinToMeasure));
  ddr = portDIRRegister(digitalPinToPort(pinToMeasure));
  bitmask = 1 << pinToMeasure;
  pin =  portDATARegister(digitalPinToPort(pinToMeasure));
  


  
  
  // Discharge the pin first by setting it low and output
  *port &= ~(bitmask);
  *ddr  |= bitmask;
  delay(1);
  // Make the pin an input WITHOUT the internal pull-up on
  *ddr &= ~(bitmask);
  // Now see how long the pin to get pulled up
  int cycles = 100;
  for(int i = 0; i < cycles; i++){
    if (*pin & bitmask){
      cycles = i;
      break;
    }
  }
  // Discharge the pin again by setting it low and output
  //  It's important to leave the pins low if you want to 
  //  be able to touch more than 1 sensor at a time - if
  //  the sensor is left pulled high, when you touch
  //  two sensors, your body will transfer the charge between
  //  sensors.
  *port &= ~(bitmask);
  *ddr  |= bitmask;
 
  return cycles;
}
Link to post
Share on other sites

Ideally one would hook the pin up to an oscilloscope and see what happening.

 

I would start by testing the function of the various little incantations (e.g. does it output a low when you think it should).

Applying some of the functions to one of the LED pins (not necessarily as part of readCapacitivePin - just as pieces).

Test to be sure each piece does what think it does.

 

I would check the energia startup code and the chip documentation to be sure that pull (up/down) is not enabled on the pin.

 

How long do you expect it to take to charge the pin (given the resistor value and voltage you are using).

 

What values are readCapacitivePin returning?  Do they change if you touch the touch sensor?

How did you arrive at the 60 threshold?  (It says to experiment - so what experiments did you do to calibrate it?)

Link to post
Share on other sites

I did some tests and concluded that my port definitions are the source of my issues.

 

The value readCapacitivePin returns is 128. This is the case when I change the pins, the number of cycles, the resistor value and so on, meaning it will always be 128

 

This section of my code where I defined the port is likely the source as I checked on the oscilloscope does not give me a RC waveform:

  volatile uint32_t* port; //use digitalWrite
  volatile uint32_t* ddr; //use pinMode
  volatile uint32_t* pin; //use digitalRead
  // Here we translate the input pin number from
  //  Arduino pin number to the AVR PORT, PIN, DDR,
  //  and which bit of those registers we care about.
  byte bitmask;
 
  // port = (uint8_t*) &P1OUT;
  // ddr = (uint8_t*) &P1DIR;
  //bitmask = 1 << pinToMeasure;
  // pin = (uint8_t*) &P1IN;

  port = portDATARegister(digitalPinToPort(pinToMeasure)); //Input
  ddr = portDIRRegister(digitalPinToPort(pinToMeasure)); //Direction
  bitmask = 1 << pinToMeasure;
  pin =  portDATARegister(digitalPinToPort(pinToMeasure)); //Output
  

I looked at the documents on the pins and on energia but got nowhere as I could not get the real port,ddr and pin.

Link to post
Share on other sites

Okay, I found out that using pinMode, digitalWrite and digitalRead works and I can understand how my capacitive sensor is implemented. I got my sensor to get the number of cycles I am expecting since it is allowing the sensor to be discharged and charged at a rate where I can get better readings.

Since the board is running at 80MHz, one cycle is 0.0125us so if I am not touching the pin, the value will be around 40 cycles with 4M ohm pulling it high. Then if I touch the sensor, the number jumps to ~200.

 

I am still figuring out why the port manipulation does not work but the pinMode, digitalWrite and digitalRead works.

 

Here is how I defined my readCapacitancePin() without port manipulation:

uint32_t readCapacitivePin(int pinMeasure){

  //First Discharge the pin before starting
  pinMode(pinMeasure,OUTPUT);
  digitalWrite(pinMeasure,LOW);
  delay(1);

  //Charging the pin to HIGH without internal pull up
  //have an external resistor to pull up the pin to +5V
  pinMode(pinMeasure,INPUT); 

  int cycles = 2000; //The tiva board clk is at 80MHz, tested which large value would be enough for the pin to charge and discharge the sensor
  //External pull-up is around 4M Ohm to +5V
  for(int i = 0; i < cycles; i++){
    if(digitalRead(pinMeasure) == HIGH){
      cycles = i;
      break;
    }
  }

  //Discharge the pin for more readings in the future
  pinMode(pinMeasure,OUTPUT);
  digitalWrite(pinMeasure,LOW);
  pinMode(pinMeasure,INPUT);


  return cycles;


}

Is it when pin is defined to portDATARegister(digitalPinToPort(pinToMeasure)) that it cannot tell if this is referring as an input or output so that is why every time I touch the sensor the number of cycles always the fixed value I put in readCapacitancePin()?

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...