FeatherM0 analogRead(A7) problem

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
k3ll
 
Posts: 11
Joined: Mon Nov 26, 2012 12:18 pm

FeatherM0 analogRead(A7) problem

Post by k3ll »

Having a problem where calling analogRead(A7) causes my code to go off the rails when attempting to read VBAT. Code worked fine on a 32u4 LoRa Feather.

Hardware:
Feather M0 LoRa
OLED FeatherWing
AdaLogger FeatherWing
...all mounted on a tripler board

Sofware:
Arduino IDE 1.83 on Windows 7
Arduino SAMD Board 1.6.15
Adafruit SAMD Boards 1.0.19


My suspicion is that the buttons (A,B,C, especially A on D9) on the OLED FeatherWing are creating a conflict with A7. As a test, I compiled and ran the code without any problems using A0 through A5 in place of A7 in analogRead(...).

Pressing the A button on the OLED FeatherWing causes the orange/yellow LED to pulse, but I have no code which controls that LED (it looks hard to do!).

I did read this year old post that seemed to solve the problem but, wonder if there was a regression defect sometime in the last year viewtopic.php?f=57&t=100823&p=505083&hi ... ex#p505083. Doesn't seem like a good idea to roll everything back to year old stuff.

Or maybe something else is in play.

Thanks,

Cliff

User avatar
adafruit_support_carter
 
Posts: 29167
Joined: Tue Nov 29, 2016 2:45 pm

Re: FeatherM0 analogRead(A7) problem

Post by adafruit_support_carter »

Does it work OK by itself? Not in the tripler or attched to any of the wings. Also, describe 'off the rails' in more detail.

User avatar
k3ll
 
Posts: 11
Joined: Mon Nov 26, 2012 12:18 pm

Re: FeatherM0 analogRead(A7) problem

Post by k3ll »

Yes, it works fine when the Feather M0 w/LoRa is standalone - meaning the VBAT code snippet in the product tutorial works fine.

By "off the rails", the program does not function as expected when the buttons on the OLED display are pressed. It behaves as if program memory has been overwritten. Over time, the program simply crashes. The buttons increment/decrement a two dimensional int array which controls what is displayed on the OLED FeatherWing. If analongRead(A7) is replaced with A0, A1, A2, A3, A4, or A5, then everything works fine.

For the OLED FeatherWing, the buttons are defined as:

Code: Select all

#define BUTTON_A 9
#define BUTTON_B 6
#define BUTTON_C 5
...and then the pinModes are set:

Code: Select all

pinMode(BUTTON_A, INPUT_PULLUP);
pinMode(BUTTON_B, INPUT_PULLUP);
pinMode(BUTTON_C, INPUT_PULLUP);
pinMode(VBATPIN, INPUT);
I think the issue is with BUTTON_A and VBATPIN.

User avatar
k3ll
 
Posts: 11
Joined: Mon Nov 26, 2012 12:18 pm

Re: FeatherM0 analogRead(A7) problem

Post by k3ll »

...forgot to add, the pin is being told to be both an analog input (no pull up) and digital input (with pull up).

https://learn.adafruit.com/adafruit-fea ... nd-pullups

User avatar
adafruit_support_carter
 
Posts: 29167
Joined: Tue Nov 29, 2016 2:45 pm

Re: FeatherM0 analogRead(A7) problem

Post by adafruit_support_carter »

Hmmm. Yeah. So something with the setup. Post a photo of your setup and complete code that demonstrates the issue.

User avatar
k3ll
 
Posts: 11
Joined: Mon Nov 26, 2012 12:18 pm

Re: FeatherM0 analogRead(A7) problem

Post by k3ll »

Here is the code. It is quite peppered with various commented out sections that were a result of debugging activities.

Code: Select all


// LoRaNodeV1M0

#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
// Required for Serial on Zero based boards

#define Serial SERIAL_PORT_USBVIRTUAL
#endif

#include <SPI.h>
#include <Wire.h>

#include <RTClib.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SD.h>


#define USE_SERIAL_DEBUG
#define USE_SD
#undef USE_LORA
// LoRa Node
//
// This is the code that the sensors are wired to and connects via LoRa to the master unit

const char* NetworkID = "A";
const char* NodeID = "1";
const int BroadcastSecs = 5;



int thepin = A5;

#ifdef USE_LORA
#include <RH_RF95.h>
#endif

//LoRa for feather m0  
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 3

#define VBATPIN A7

Adafruit_SSD1306 display = Adafruit_SSD1306();

#if defined(ESP8266)
#define BUTTON_A 0
#define BUTTON_B 16
#define BUTTON_C 2
#define LED      0
#elif defined(ESP32)
#define BUTTON_A 15
#define BUTTON_B 32
#define BUTTON_C 14
#define LED      13
#elif defined(ARDUINO_STM32F2_FEATHER)
#define BUTTON_A PA15
#define BUTTON_B PC7
#define BUTTON_C PC5
#define LED PB5
#elif defined(TEENSYDUINO)
#define BUTTON_A 4
#define BUTTON_B 3
#define BUTTON_C 8
#define LED 13
#elif defined(ARDUINO_FEATHER52)
#define BUTTON_A 31
#define BUTTON_B 30
#define BUTTON_C 27
#define LED 17
#else // 32u4, M0, and 328p
#define BUTTON_A 9
#define BUTTON_B 6
#define BUTTON_C 5
#define LED      13
#endif

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif


// Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 915.0
#ifdef USE_LORA
// Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);
#endif
RTC_PCF8523 rtc;
DateTime now;

#ifdef  USE_SD
// SD card
const int chipSelect = 10;   // for SD card on Feather
File LogFile;
#endif //  USE_SD

int TXCount = 0;
char tmp[256];
char tmp32[32];
char tmp16[16];
char tmp8[8];
//char RXBuffer[256];
char TXBuffer[256];
char DateTimeString[64];
char VersionDate[16];
char VersionTime[16];
// display page control
int ButtonCount[3][2];


struct SensorsStruct
{
	char Name[16];
	char Value[16];
	char UOM[16];
	char ChannelID[4];
	bool Upoad;
} Sensors[16];

int SensorCount = 0;
int SensorTotalCount = 0;

int LastSeconds = -1000;
int ThisSeconds = 0;

char WhirlyGigCharacter;

char Parameter[64];

void setup()
{
	delay(500);

	// configure the buttons on the display
	ButtonCount[0][0] = 1;  // default page = 1
	ButtonCount[0][1] = 2;  // number of pages

	ButtonCount[1][0] = 0;  // not default page
	ButtonCount[1][1] = 4;  // number of pages

	ButtonCount[2][0] = 0;  // not default page
	ButtonCount[2][1] = 0;  // number of pages - this will be overwritten by Sensors() based on number of sensors

	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
	display.clearWriteError();

	display.setTextSize(2);  // this is a multiplier: 1, 2, 3 and 4 are normal values
	display.setTextColor(WHITE);
	strcpy(Parameter, "Firmware\nReleased...");
	DisplayMessage(Parameter);
	delay(1500);
	// month part
	strncpy(tmp32, __DATE__, 3);
	tmp32[3] = '\0';
	if (strcmp("Jan", tmp32) == 0)
		strcpy(tmp8, "01");
	else if (strcmp("Feb", tmp32) == 0)
		strcpy(tmp8, "02");
	else if (strcmp("Mar", tmp32) == 0)
		strcpy(tmp8, "03");
	else if (strcmp("Apr", tmp32) == 0)
		strcpy(tmp8, "04");
	else if (strcmp("May", tmp32) == 0)
		strcpy(tmp8, "05");
	else if (strcmp("Jun", tmp32) == 0)
		strcpy(tmp8, "06");
	else if (strcmp("Jul", tmp32) == 0)
		strcpy(tmp8, "07");
	else if (strcmp("Aug", tmp32) == 0)
		strcpy(tmp8, "08");
	else if (strcmp("Sep", tmp32) == 0)
		strcpy(tmp8, "09");
	else if (strcmp("Oct", tmp32) == 0)
		strcpy(tmp8, "10");
	else if (strcmp("Nov", tmp32) == 0)
		strcpy(tmp8, "11");
	else if (strcmp("Dec", tmp32) == 0)
		strcpy(tmp8, "12");
	// year part
	strcpy(tmp32, __DATE__);
	strncpy(tmp16, &tmp32[7], 4);
	tmp16[4] = '\0';
	// day part
	strncpy(tmp, &tmp32[4], 2);
	if (tmp[0] == ' ')
		tmp[0] = '0';
	tmp[2] = '\0';
	strcpy(tmp32, tmp);

	sprintf(tmp, "%s-%s-%s\n%s P", tmp16, tmp8, tmp32, __TIME__);

	sprintf(VersionDate, "%s-%s-%s", tmp16, tmp8, tmp32);
	sprintf(VersionTime, "%s P", __TIME__);

	DisplayMessage(tmp);
	delay(1500);
	pinMode(LED_BUILTIN, OUTPUT);
	pinMode(BUTTON_A, INPUT_PULLUP);
	pinMode(BUTTON_B, INPUT_PULLUP);
	pinMode(BUTTON_C, INPUT_PULLUP);
	pinMode(VBATPIN, INPUT);
	pinMode(A2, INPUT);
	pinMode(10, OUTPUT);
	delay(2000);
#ifdef  USE_SD
	strcpy(Parameter, "Init\nSD Card...");
	DisplayMessage(Parameter);
	if (!SD.begin(chipSelect))
	{
		strcpy(Parameter, "SD Card\nFailed!");
		DisplayMessage(Parameter);
		delay(7000);
		return;
	}
#endif
	delay(2000);
#ifdef USE_SERIAL_DEBUG
	strcpy(Parameter, "Init\nSerial...");
	DisplayMessage(Parameter);
	Serial.begin(9600);
	delay(100);
#endif
#ifdef USE_LORA
	strcpy(Parameter, "Init\BANNED...");
	DisplayMessage(Parameter);
	pinMode(RFM95_RST, OUTPUT);
	digitalWrite(RFM95_RST, HIGH);
	// manual reset
	digitalWrite(RFM95_RST, LOW);
	delay(10);
	digitalWrite(RFM95_RST, HIGH);
	delay(10);
	while (!rf95.init())
	{
		strcpy(Parameter, "Init\BANNED Failed!");
		DisplayMessage(Parameter);
		while (1);
	}
	// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM

	if (!rf95.setFrequency(RF95_FREQ))
	{
		strcpy(Parameter, "Set Freq Failed!");
		DisplayMessage(Parameter);
		while (1);
	}
	delay(2000);
	// Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
	// The default transmitter power is 13dBm, using PA_BOOST.
	// If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then 
	// you can set transmitter powers from 5 to 23 dBm:
	rf95.setTxPower(23, false);
#endif

	if (!rtc.begin())
	{
		strcpy(Parameter, "RTC Failed!");
		DisplayMessage(Parameter);
		while (1);
	}
	delay(100);
	if (!rtc.initialized())
	{
		strcpy(Parameter, "Init\nClock...");
		DisplayMessage(Parameter);
		// Serial.println("RTC is NOT running!");
		// following line sets the RTC to the date & time this sketch was compiled
		// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
		// This line sets the RTC with an explicit date & time, for example to set
		rtc.adjust(DateTime(2000, 1, 1, 00, 00, 0));
	}

	// use this to initialize the clock one time
	// this is local time not the preferred UTC time, but good enough for testing
	rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

	WhirlyGig(true);
	strcpy(Parameter, "Ready");
	DisplayMessage(Parameter);
	delay(1500);
}


void loop()
{

	now = rtc.now();
	sprintf(DateTimeString, "%4d-%02d-%02d %02d:%02d:%02d", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
	WhirlyGigCharacter = WhirlyGig(false);
	SensorsRead();

	delay(50);

	// Home Button
	if (!digitalRead(BUTTON_A))
	{
		if (KeyPress(BUTTON_A, false))
		{
			ButtonCount[0][0] = ((ButtonCount[0][0]++) % ButtonCount[0][1]) + 1;
			ButtonCount[1][0] = 0;
			ButtonCount[2][0] = 0;
			//Serial.println(ButtonCount[0][0], DEC);
		}

	}
	// Configuration Button
	if (!digitalRead(BUTTON_B))
	{
		if (KeyPress(BUTTON_B, false))
		{
			ButtonCount[0][0] = 0;
			ButtonCount[1][0] = ((ButtonCount[1][0]++) % ButtonCount[1][1]) + 1;
			ButtonCount[2][0] = 0;
			//Serial.println(ButtonCount[1][0], DEC);
		}

	}
	// Sensors Button
	if (!digitalRead(BUTTON_C))
	{
		if (KeyPress(BUTTON_C, false))
		{
			ButtonCount[2][0] = ((ButtonCount[2][0]++) % SensorTotalCount) + 1;
			ButtonCount[0][0] = 0;
			ButtonCount[1][0] = 0;
			//Serial.println(ButtonCount[2][0], DEC);
		}

	}

	//*********************************************
	// set active display based on button settings
	//*********************************************
	display.clearDisplay();
	display.setCursor(0, 0);
	// Home Button
	// 1 = VaporSafe/Date
	if (ButtonCount[0][0] == 1)
	{
		strcpy(tmp32, &DateTimeString[11]);
		sprintf(tmp, "%cVaporSafe\n%s Z", WhirlyGigCharacter, tmp32);
		if (now.second() % 2 == 0)
			ButtonCount[0][0] = 2;
	}
	// Home Button
	// 1 = VaporSafe/Time
	else if (ButtonCount[0][0] == 2)
	{
		strncpy(tmp32, DateTimeString, 10);
		tmp32[10] = '\0';
		sprintf(tmp, "%cVaporSafe\n%s", WhirlyGigCharacter, tmp32);
		if (now.second() % 2 == 1)
			ButtonCount[0][0] = 1;
	}
	// Configuration Button
	// 1 = Date/Time
	// 2 = Network/Node
	// 3 = Firmware Version Date
  // 4 = Firmware Version Time
	else if (ButtonCount[1][0] == 1)
	{
		DateTimeString[10] = '\n';
		DateTimeString[19] = ' ';
		DateTimeString[20] = 'Z';
		DateTimeString[21] = '\0';
		strcpy(tmp, DateTimeString);
	}
	else if (ButtonCount[1][0] == 2)
	{
		strcpy(tmp, "Network:A\nNode:1");
	}
	else if (ButtonCount[1][0] == 3)
	{
		strcpy(tmp, "Ver Date:\n");
		strcat(tmp, VersionDate);
	}
	else if (ButtonCount[1][0] == 4)
	{
		strcpy(tmp, "Ver Time:\n");
		strcat(tmp, VersionTime);
	}
	// Sensor button
	// scroll through all of the Sensors[]
	else if (ButtonCount[2][0] > 0)
	{
		sprintf(tmp, "%c %s\n%s %s", WhirlyGigCharacter, Sensors[ButtonCount[2][0] - 1].Name, Sensors[ButtonCount[2][0] - 1].Value, Sensors[ButtonCount[2][0] - 1].UOM);
	}
	else
	{
		sprintf(tmp, "%cButtons\n%d%d %d%d %d%d", WhirlyGigCharacter, ButtonCount[0][0], ButtonCount[0][1], ButtonCount[1][0], ButtonCount[1][1], ButtonCount[2][0], ButtonCount[2][1]);
	}
	//sprintf(tmp, "%cButtons\n%d%d %d%d %d%d", WhirlyGigCharacter, ButtonCount[0][0], ButtonCount[0][1], ButtonCount[1][0], ButtonCount[1][1], ButtonCount[2][0], ButtonCount[2][1]);

	display.print(tmp);
	display.display();


	ThisSeconds = now.second();
	// check to see if we should send the data
	if (abs(LastSeconds - ThisSeconds) >= BroadcastSecs)
	{
		TXCount++;
		strcpy(TXBuffer, DateTimeString);
		//sprintf(TXBuffer, "*%s|%s|%d|114|%s|%s", NetworkID, NodeID, TXCount, DateTimeString);
		//for (int i = 0; i < SensorTotalCount; i++)
		//{
		//	if (Sensors[i].Upoad)
		//	{
		//		strcat(TXBuffer, "|");
		//		strcat(TXBuffer, Sensors[i].ChannelID);
		//		strcat(TXBuffer, "|");
		//		strcat(TXBuffer, Sensors[i].Value);
		//		strcat(TXBuffer, "\n");

		//	}
		//}
		// Debug(TXBuffer);
		//LogData(TXBuffer);
		// tx(TXBuffer);
		LastSeconds = ThisSeconds;
	}


}


#ifdef USE_LORA
bool tx(char *Packet)
{
	bool Success = false;
	digitalWrite(LED_BUILTIN, HIGH);
	// Serial.println("Sending to rf95_server");
	// Send a message to rf95_server

	//char radiopacket[20] = "Hello World #      ";

	// Serial.print("Sending "); Serial.println(radiopacket);
	//radiopacket[19] = 0;

	//Serial.println("Sending..."); delay(10);
	rf95.send((uint8_t *)Packet, strlen(Packet));

	//Serial.println("Waiting for packet to complete..."); delay(10);
	rf95.waitPacketSent();
	// Now wait for a reply
	uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
	uint8_t len = sizeof(buf);

	//Serial.println("Waiting for reply..."); 
	delay(10);
	if (rf95.waitAvailableTimeout(1100))
	{
		// Should be a reply message for us now   
		if (rf95.recv(buf, &len))
		{
			Success = true;
			//Debug("Got reply: ");
			//Debug((char*)buf);
			//Debug("RSSI: ");
			//Serial.println(rf95.lastRssi(), DEC);   
		}
		else
		{
			//Debug("Receive failed");
		}
	}
	else
	{
		//Debug("No reply, is there a listener around?");
	}
	delay(1);
	digitalWrite(LED_BUILTIN, LOW);
	return(Success);
}
#endif

/*
void rx()
{

  if (rf95.available())
  {
	// Should be a message for us now
	uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
	uint8_t len = sizeof(buf);

	if (rf95.recv(buf, &len))
	{
	  digitalWrite(LED, HIGH);
	  RH_RF95::printBuffer("Received: ", buf, len);
	  strncpy(RXBuffer, (char*)buf, len);
	  RXBuffer[len] = '\0';
	  Serial.print("Got: ");
	  Serial.println(RXBuffer);
	  Serial.print("RSSI: ");
	  Serial.println(rf95.lastRssi(), DEC);
	  delay(10);

	  digitalWrite(LED, LOW);
	  RXCount++;
	}
	else
	{
	  //Serial.println("Receive failed");
	}
  }
}

*/

char WhirlyGig(bool Init)
{
	static byte Position;
	if (Init)
		Position = -1;

	Position++;

	if (Position == 0)
		return(124); // |
	if (Position == 1)
		return(47); // /
	if (Position == 2)
		return(45); // -
	if (Position == 3)
		return(92);  // backslash
	if (Position == 4)
		return(124); // |
	if (Position == 5)
		return(47); //
	if (Position == 6)
		return(45); // -
	if (Position == 7)
	{
		Position = -1;
		return(92); //  backslash
	}
	return('*');  // indicates an error
}


void Debug(char *s)
{
#ifdef USE_SERIAL_DEBUG
	Serial.println(s);
#endif

}

void DisplayMessage(char *Message)
{
	display.clearDisplay();
	display.setCursor(0, 0);
	display.print(Message);
	display.display();
}

void LogData(char *data)
{
#ifdef  USE_SD
	LogFile = SD.open("q.txt", FILE_WRITE);
	if (LogFile)
	{
		LogFile.println(data);
		LogFile.close();
	}
	else
	{
		strcpy(Parameter, "SD Card Problem");
		DisplayMessage(Parameter);
		delay(5000);
	}
#endif
}

float SensorBatteryVoltage(int Pin)
{
	float ADResolution = 1024.0;
	float measuredvbat = 0;
	if (Pin != A7)
		measuredvbat = analogRead(A7);
	measuredvbat = measuredvbat * 6.6;
	measuredvbat /= ADResolution; // convert to voltage
	return(measuredvbat);
}

float SensorDiffPressure(int pin)
{
	float ADResolution = 4096.0;
	float measuredvbat = analogRead(thepin);

	measuredvbat = measuredvbat * 6.6;
	measuredvbat /= ADResolution; // convert to voltage
	return(measuredvbat);
}

bool KeyPress(int Pin, bool PressedState)
{
	unsigned long Startms = millis();
	unsigned long Diffms = millis() - Startms;
	bool CurrentState = PressedState;

	do
	{
		CurrentState = digitalRead(Pin);
		Diffms = millis() - Startms;
	} while ((Diffms < 10) && (CurrentState == PressedState));

	return(CurrentState == PressedState);

}



void SensorsRead()
{
	int i = 0;


	int ADValue = 0;
	ADValue = analogRead(thepin);

	strcpy(Sensors[i].Name, "Uptime");
	strcpy(Sensors[i].UOM, "Secs");
	sprintf(tmp, "%lu", millis() / 1000);
	strcpy(Sensors[i].Value, tmp);
	strcpy(Sensors[i].ChannelID, "0");
	Sensors[i].Upoad = true;
	i++;


	strcpy(Sensors[i].Name, "Bat Volt");
	strcpy(Sensors[i].UOM, "VDC");
	dtostrf(SensorBatteryVoltage(), 3, 2, tmp);
	strcpy(Sensors[i].Value, tmp);
	strcpy(Sensors[i].ChannelID, "0");
	Sensors[i].Upoad = true;
	i++;

	strcpy(Sensors[i].Name, "Bat Volt");
	strcpy(Sensors[i].UOM, "A/D");
	sprintf(tmp, "%d", 1);
	strcpy(Sensors[i].Value, tmp);
	strcpy(Sensors[i].ChannelID, "0");
	Sensors[i].Upoad = true;
	i++;

	strcpy(Sensors[i].Name, "DiffPrss");
	strcpy(Sensors[i].UOM, "Pa");
	dtostrf(SensorDiffPressure(ADValue), 3, 1, tmp);
	strcpy(Sensors[i].Value, tmp);
	strcpy(Sensors[i].ChannelID, "0");
	Sensors[i].Upoad = true;
	i++;

	strcpy(Sensors[i].Name, "DiffPrss");
	strcpy(Sensors[i].UOM, "A/D");
	sprintf(tmp, "%d", ADValue);
	strcpy(Sensors[i].Value, tmp);
	strcpy(Sensors[i].ChannelID, "0");
	Sensors[i].Upoad = false;
	i++;


	strcpy(Sensors[i].Name, "End Of\nSensors");
	strcpy(Sensors[i].UOM, "");
	strcpy(Sensors[i].Value, "");
	strcpy(Sensors[i].ChannelID, "0");
	Sensors[i].Upoad = false;
	i++;
	SensorTotalCount = i;

}



char *dtostrf(double value, int width, unsigned int precision, char *result)
{
	int decpt, sign, reqd, pad;
	const char *s, *e;
	char *p;
	s = fcvt(value, precision, &decpt, &sign);
	if (precision == 0 && decpt == 0) {
		s = (*s < '5') ? "0" : "1";
		reqd = 1;
	}
	else {
		reqd = strlen(s);
		if (reqd > decpt) reqd++;
		if (decpt == 0) reqd++;
	}
	if (sign) reqd++;
	p = result;
	e = p + reqd;
	pad = width - reqd;
	if (pad > 0) {
		e += pad;
		while (pad-- > 0) *p++ = ' ';
	}
	if (sign) *p++ = '-';
	if (decpt <= 0 && precision > 0) {
		*p++ = '0';
		*p++ = '.';
		e++;
		while (decpt < 0) {
			decpt++;
			*p++ = '0';
		}
	}
	while (p < e) {
		*p++ = *s++;
		if (p == e) break;
		if (--decpt == 0) *p++ = '.';
	}
	if (width < 0) {
		pad = (reqd + width) * -1;
		while (pad-- > 0) *p++ = ' ';
	}
	*p = 0;
	return result;
}




User avatar
k3ll
 
Posts: 11
Joined: Mon Nov 26, 2012 12:18 pm

Re: FeatherM0 analogRead(A7) problem

Post by k3ll »

You will want to modify this function, which has a temporary workaround:

Code: Select all

float SensorBatteryVoltage(int Pin)
{
	float ADResolution = 1024.0;
	float measuredvbat = 0;
	if (Pin != A7)
		measuredvbat = analogRead(A7);
	measuredvbat = measuredvbat * 6.6;
	measuredvbat /= ADResolution; // convert to voltage
	return(measuredvbat);
}

User avatar
k3ll
 
Posts: 11
Joined: Mon Nov 26, 2012 12:18 pm

Re: FeatherM0 analogRead(A7) problem

Post by k3ll »

Here is the pic - pretty basic, however I did add a 100uF capacitor between VCC and ground in order to address an issue with the RTC FeatherWing. You can't see it because it is underneath the component side of the board.

viewtopic.php?f=57&t=98219&p=599241&hil ... me#p599241
20170807_094024.jpg
20170807_094024.jpg (229.37 KiB) Viewed 1223 times

User avatar
adafruit_support_carter
 
Posts: 29167
Joined: Tue Nov 29, 2016 2:45 pm

Re: FeatherM0 analogRead(A7) problem

Post by adafruit_support_carter »

Looks like battery sense and digital input 9 are tied together. And button A of the OLED Feather Wing is attached to digital 9. So they are going to interfere. But I'm seeing the same conflict on the 32u4 board as well. How did you get it to work there?

User avatar
k3ll
 
Posts: 11
Joined: Mon Nov 26, 2012 12:18 pm

Re: FeatherM0 analogRead(A7) problem

Post by k3ll »

It works on the 32u4 because VBATPIN is on A9, not A7 as in the M0 since it has fewer A/Ds. Seems like the solution is to move VBATPIN on the M0 somewhere else (A0-A5).

https://learn.adafruit.com/adafruit-fea ... ng-battery

User avatar
adafruit_support_carter
 
Posts: 29167
Joined: Tue Nov 29, 2016 2:45 pm

Re: FeatherM0 analogRead(A7) problem

Post by adafruit_support_carter »

True. But they are both physically connected to the same ~9 pin on the Feather header, which is where button A from the OLED will come in. So I'd expect the interference to be there on both.

Or to put it another way, the voltage divider is physically connected to ~9, so whatever is attached there is going to interfere with battery sense.
32u4.jpg
32u4.jpg (207.43 KiB) Viewed 1193 times
m0.jpg
m0.jpg (261.97 KiB) Viewed 1193 times

User avatar
k3ll
 
Posts: 11
Joined: Mon Nov 26, 2012 12:18 pm

Re: FeatherM0 analogRead(A7) problem

Post by k3ll »

Ah yes, your'e right!

I think that is why I was heading down the SAMD path with this. I've been struggling with it all weekend since I received the M0 boards on Friday.

Perhaps it is something specific about the M0 internals. Maybe related to the inputs and pullup changes from the 32u4?

User avatar
adafruit_support_carter
 
Posts: 29167
Joined: Tue Nov 29, 2016 2:45 pm

Re: FeatherM0 analogRead(A7) problem

Post by adafruit_support_carter »

Maybe related to the inputs and pullup changes from the 32u4?
They're very different chips, but still, either should have an issue. Pressing the button on the OLED will short the input to ground which will throw off the reading. Although either should work as long as the button is not pressed.

I guess you can either sense the battery or read BUTTON A, but not both. At least not at the same time. So by doing this:

Code: Select all

   pinMode(BUTTON_A, INPUT_PULLUP);
   pinMode(BUTTON_B, INPUT_PULLUP);
   pinMode(BUTTON_C, INPUT_PULLUP);
   pinMode(VBATPIN, INPUT);
You're setting the pin up twice. Once via BUTTON_A and again via VBATPIN. Haven't looked through your code fully, but can imagine that could cause grief/confusion. And also possible the details would be different between 32u4 and M0.
Pressing the A button on the OLED FeatherWing causes the orange/yellow LED to pulse, but I have no code which controls that LED
What/where was this LED?

User avatar
k3ll
 
Posts: 11
Joined: Mon Nov 26, 2012 12:18 pm

Re: FeatherM0 analogRead(A7) problem

Post by k3ll »

The on board LED is next to Reset button on the M0 and is labelled CHG.

Yes, ironically I was just using the VBAT code to test the A/D and user interface, which was fine on the 32u4. I entered this cul de sac when porting 32u4 code to the M0, so ditching the A7 input is not a show stopper. My entire system will be powered by 12VDC, so I will just run a divider off of that and wire it to another analog input.

Probably a good idea to update the docs on both the M0 and OLED pages.

Thanks for you help!

Cliff

User avatar
adafruit_support_carter
 
Posts: 29167
Joined: Tue Nov 29, 2016 2:45 pm

Re: FeatherM0 analogRead(A7) problem

Post by adafruit_support_carter »

Will pass this along. May be worth making the guide(s) more explicit about potential interference between D9 and the battery sense. It's there, but kind of implicit and terse.

FWIW, the guides do mention the correct analog inputs for the battery sense and have proper example code.
For 32u4 (A9):
https://learn.adafruit.com/adafruit-fea ... ng-battery
and the M0 (A7):
https://learn.adafruit.com/adafruit-fea ... ng-battery
so if porting from 32u4 to M0, at a minimum you'd need to change that in the code. But doesn't fix the problem with being tied to D9, so:
I will just run a divider off of that and wire it to another analog input.
seems like a good solution for your setup.

Locked
Please be positive and constructive with your questions and comments.

Return to “Microcontrollers”