!Qwert 0 Posted October 16, 2014 Share Posted October 16, 2014 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: http://forum.43oh.com/topic/5166-need-advice-porting-arduino-code-to-energia/ That this is using peripheral names on the MSP430 regarding registers P1DIR - to set directionP1OUT - 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 Quote Link to post Share on other sites
igor 163 Posted October 17, 2014 Share Posted October 17, 2014 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. energia 1 Quote Link to post Share on other sites
!Qwert 0 Posted October 18, 2014 Author Share Posted October 18, 2014 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. Quote Link to post Share on other sites
igor 163 Posted October 18, 2014 Share Posted October 18, 2014 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. Quote Link to post Share on other sites
igor 163 Posted October 18, 2014 Share Posted October 18, 2014 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) Seehttp://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.] Quote Link to post Share on other sites
!Qwert 0 Posted October 18, 2014 Author Share Posted October 18, 2014 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. Quote Link to post Share on other sites
igor 163 Posted October 19, 2014 Share Posted October 19, 2014 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). Quote Link to post Share on other sites
!Qwert 0 Posted October 21, 2014 Author Share Posted October 21, 2014 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; } Quote Link to post Share on other sites
igor 163 Posted October 22, 2014 Share Posted October 22, 2014 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?) Quote Link to post Share on other sites
!Qwert 0 Posted October 23, 2014 Author Share Posted October 23, 2014 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. Quote Link to post Share on other sites
!Qwert 0 Posted October 26, 2014 Author Share Posted October 26, 2014 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()? OzGrant 1 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.