I2C adress för MCP4728 beter sig konstigt?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
agehall
Inlägg: 418
Blev medlem: 12 augusti 2020, 19:27:54

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av agehall »

Beroende på multimeter så kan de ta rätt god tid på sig att reagera. Ska du titta på hur signaler ändrar värde är inte en multimeter rätt verktyg.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av sodjan »

Och dessutom, det är helt fel att jämföra en DMM med en DAC.
(Hade missat att det var en DAC, och inte en ADC...)

En DAC har ingen "conversion time", den har en "settling time".
I detta fall är det (typ) 6 us. Alltså tiden från att ett register har
skrivits till att analog utgången är inom 1/2 LSB.

Så jämförelsen med en DMM är komplett irrelevant...
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4689
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av Swech »

Hela tråden handlar ju om att SPI delen inte fungerar som tänkt,
det funkar nästan men med småproblem med i princip allt.
Om man då är lite ödmjuk och inte antar att Microchip gjort fel
utan istället gör en normal felsökning och bekräftar att man verkligen har rätt signaler på bussen,
ACK är i sig en lurig jävel att få till rätt. OM det är fel så kan felen bli så som tråden beskriver....

Swech
ToPNoTCH
Inlägg: 4847
Blev medlem: 21 december 2009, 17:59:48

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av ToPNoTCH »

DanielM skrev: 5 maj 2022, 22:32:38 Även ST själva använder datatypen __weak. Eller i alla fall ordet __weak.
Du motiverar en single underline framför en HandleDefinition med att ST gör detta med dubbel underline i ett kompiler direktiv.
Dom har ABSOLUT inget med varann att göra ens och bara det att du tar upp detta som ett exempel gör det pinsamt tydligt att du sitter och gissar.

__weak betyder i för ST kompilator på ren Svenska att "Om den här rutinen finns definierad någon annanstans så använd den istället"
Syftet är att i CubeMX automatgenererade kod så görs anrop till callbackrutiner (exempelvis) vilka förväntas att användaren skapar själv om man vill nyttja dom.

För att inte få kompileringsfel OM användaren inte har sådan, så fyller dom på med fördefinierade __weak funtioner (dom är oftast tomma).

Det här skrev jag i en annan tråd då jag märkte att du själv lade till __weak framför dina egna rutiner utan att ens veta varför du gjorde det eller vilken betydelse det har.

Det verkar ännu inte ha gått in.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av DanielM »

Swech skrev: 6 maj 2022, 09:31:48 Hela tråden handlar ju om att SPI delen inte fungerar som tänkt,
det funkar nästan men med småproblem med i princip allt.
Om man då är lite ödmjuk och inte antar att Microchip gjort fel
utan istället gör en normal felsökning och bekräftar att man verkligen har rätt signaler på bussen,
ACK är i sig en lurig jävel att få till rätt. OM det är fel så kan felen bli så som tråden beskriver....

Swech
Om jag behöver fördröjningar så betyder det att chippet är rätt segt av sig?
Användarvisningsbild
rvl
Inlägg: 5720
Blev medlem: 5 april 2016, 14:58:53
Ort: Helsingfors

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av rvl »

Mer troligt för att komma runt nån (egen) bug.
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4689
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av Swech »

Om du behöver fördröjningar så har du fel på kommunikationen

Swech
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av DanielM »

Ja. Men vad kan det vara. Jag kanske tolkar databladet fel?
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4689
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av Swech »

har du mätt med ett oscilloskop på bussen och kunnat verifiera att det
som kommer där är samma som du vill / tror skall vara där

Swech
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av DanielM »

Hmm.
Jag tror detta är problemet.
Skärmklipp.PNG
Sedan är det korrekt att uppdatera med att flippa på LDAC.
Skärmklipp.PNG
Det fungerar också att sätta en fördröjning på ca 50 ms.

Kod: Markera allt

void mcp4728_single_write_command(uint8_t channel, uint8_t Vref, uint8_t power_down, uint8_t gain, uint16_t value){
	const uint8_t UDAC = 0x0;
	uint8_t pData[3] = {(SINGLE_WRITE_COMMAND << 3) | (channel << 1) | UDAC, (Vref << 8) | (power_down << 5) | (gain << 4) | (value >> 8), value};
	HAL_I2C_Master_Transmit(_hi2c, _address << 1, pData, sizeof(pData), Timeout);
	HAL_Delay(50);
}
Varför? Jo, för det tar tid att skriva till EEPROM! Eller?

Så jag tror att jag SKALL använda denna funktion istället? Eller hur?
Men hur tolkar jag detta...diagram? Är allt en enda stor array?
Skärmklipp.PNG
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
ToPNoTCH
Inlägg: 4847
Blev medlem: 21 december 2009, 17:59:48

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av ToPNoTCH »

Skall du verkligen skifta vref biten åtta gånger. Borde väl vara sju i min värld.
Användarvisningsbild
JimmyAndersson
Inlägg: 26308
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av JimmyAndersson »

Åtta vore inte rätt nä.. :)


Bara av nyfikenhet:
HAL_Delay(50);

Är det millisekunder?
ToPNoTCH
Inlägg: 4847
Blev medlem: 21 december 2009, 17:59:48

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av ToPNoTCH »

Ja det är det.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av DanielM »

Nu har jag fått det att fungera för alla kanaler!
Det fanns två problem:
- Problemet med multi-write-funktionen var att man SKALL skicka I2C adressen och dess funktion i VARJE meddelande. Jag hade byte0 som I2C adress och funktion och resterande bytes använde jag som data. Jag tolkade alltså diagrammet för multi-write fel.
- Problemet med single-write funktionen var att man MÅSTE ha en fördröjning då det tar tid för EEPROM att skrivas in.

Så här ska C kod skrivas. Snyggt, rent, logiskt placerade funktioner, statiska funktioner tolkas som privata funktioner. Rätt #defines på rätt ställen(inte ha allt i header-filen), logiska namn, undvika struct så mycket som det bara går. Minimalt med kod. Rena kommentarer.

Kod: Markera allt

  /* Write to MCP4728 */
  mcp4728_init(&hi2c1, 0x4); // Manufacturer I2C settings: A4 (A2 = 1, A1 = 0, A0 = 0)

  /* Set values */
  mcp4728_set_channel_value(MCP4728_CHANNEL_A, 4095);
  mcp4728_set_channel_value(MCP4728_CHANNEL_B, 1000);
  mcp4728_set_channel_value(MCP4728_CHANNEL_C, 2000);
  mcp4728_set_channel_value(MCP4728_CHANNEL_D, 3000);

  /* Set gain */
  mcp4728_set_channel_gain(MCP4728_CHANNEL_A, MCP4728_GAIN_1);
  mcp4728_set_channel_gain(MCP4728_CHANNEL_B, MCP4728_GAIN_1);
  mcp4728_set_channel_gain(MCP4728_CHANNEL_C, MCP4728_GAIN_1);
  mcp4728_set_channel_gain(MCP4728_CHANNEL_D, MCP4728_GAIN_1);

  /* Set power down */
  mcp4728_set_channel_power_down(MCP4728_CHANNEL_A, MCP4728_POWER_DOWN_NORMAL);
  mcp4728_set_channel_power_down(MCP4728_CHANNEL_B, MCP4728_POWER_DOWN_NORMAL);
  mcp4728_set_channel_power_down(MCP4728_CHANNEL_C, MCP4728_POWER_DOWN_NORMAL);
  mcp4728_set_channel_power_down(MCP4728_CHANNEL_D, MCP4728_POWER_DOWN_NORMAL);

  /* Set voltage reference */
  mcp4728_set_channel_vref(MCP4728_CHANNEL_A, MCP4728_VREF_VDD);
  mcp4728_set_channel_vref(MCP4728_CHANNEL_B, MCP4728_VREF_VDD);
  mcp4728_set_channel_vref(MCP4728_CHANNEL_C, MCP4728_VREF_VDD);
  mcp4728_set_channel_vref(MCP4728_CHANNEL_D, MCP4728_VREF_VDD);

  /* Multi write without EEPROM */
  mcp4728_multi_write_command();

  /* Single write with EEPROM */
  mcp4728_set_channel_value(MCP4728_CHANNEL_A, 1000);
  mcp4728_single_write_command(MCP4728_CHANNEL_A);

Kod: Markera allt

#include "mcp4728.h"

static I2C_HandleTypeDef *_hi2c;
static uint8_t _address;
#define Timeout 10

#define GERNAL_CALL_COMMAND 0x0
#define GENERAL_CALL_RESET 0x6
#define GENERAL_CALL_WAKE_UP 0x9
#define SINGLE_WRITE_COMMAND 0xB
#define MULTI_WRITE_COMMAND 0x8

static uint16_t channel_value[4] = {0};
static uint8_t channel_power_down[4] = {0};
static uint8_t channel_gain[4] = {0};
static uint8_t channel_vref[4] = {0};

void static transmit_reset(){
	uint8_t pData[1] = {GENERAL_CALL_RESET};
	HAL_I2C_Master_Transmit(_hi2c, GERNAL_CALL_COMMAND, pData, sizeof(pData), Timeout);
}

void static transmit_wake_up(){
	uint8_t pData[1] = {GENERAL_CALL_WAKE_UP};
	HAL_I2C_Master_Transmit(_hi2c, GERNAL_CALL_COMMAND, pData, sizeof(pData), Timeout);
}

void mcp4728_init(I2C_HandleTypeDef *hi2c, uint8_t address){
	_hi2c = hi2c;
	_address = (0xC << 3) | address;
	transmit_reset();
	transmit_wake_up();
	HAL_GPIO_WritePin(LDAC_GPIO_Port, LDAC_Pin, GPIO_PIN_RESET);
}

void mcp4728_set_channel_value(uint8_t channel, uint16_t value){
	if(channel <= MCP4728_CHANNEL_D)
		channel_value[channel] = value;
}

void mcp4728_set_channel_power_down(uint8_t channel, uint8_t power_down){
	if(channel <= MCP4728_CHANNEL_D)
		channel_power_down[channel] = power_down;
}

void mcp4728_set_channel_gain(uint8_t channel, uint8_t gain){
	if(channel <= MCP4728_CHANNEL_D)
		channel_gain[channel] = gain;
}

void mcp4728_set_channel_vref(uint8_t channel, uint8_t vref){
	if(channel <= MCP4728_CHANNEL_D)
		channel_vref[channel] = vref;
}

void mcp4728_multi_write_command(){
	const uint8_t UDAC = 0x0;
	for(uint8_t channel = MCP4728_CHANNEL_A; channel <= MCP4728_CHANNEL_D; channel++){
		uint8_t multi_write_data[3] = {(MULTI_WRITE_COMMAND << 3) | (channel << 1) | UDAC, (channel_vref[channel] << 7) | (channel_power_down[channel] << 5) | (channel_gain[channel] << 4) | (channel_value[channel] >> 8), channel_value[channel]};
		HAL_I2C_Master_Transmit(_hi2c, _address << 1, multi_write_data, sizeof(multi_write_data), Timeout);
	}
}

void mcp4728_single_write_command(uint8_t channel){
	/* This command should only be called with a time delay about 50 ms due to the EEPROM writing */
	if(channel <= MCP4728_CHANNEL_D){
		const uint8_t UDAC = 0x0;
		uint8_t pData[3] = {(SINGLE_WRITE_COMMAND << 3) | (channel << 1) | UDAC, (channel_vref[channel] << 7) | (channel_power_down[channel] << 5) | (channel_gain[channel] << 4) | (channel_value[channel] >> 8), channel_value[channel]};
		HAL_I2C_Master_Transmit(_hi2c, _address << 1, pData, sizeof(pData), Timeout);
	}
}

Kod: Markera allt

/*
 * mcp4728.h
 *
 *  Created on: May 1, 2022
 *      Author: Daniel M
 */

#ifndef SRC_MCP4728_MCP4728_H_
#define SRC_MCP4728_MCP4728_H_

#include "main.h"
#include <stdint.h>

#define MCP4728_CHANNEL_A 0x0
#define MCP4728_CHANNEL_B 0x1
#define MCP4728_CHANNEL_C 0x2
#define MCP4728_CHANNEL_D 0x3
#define MCP4728_VREF_VDD 0x0
#define MCP4728_VREF_INTERNAL 0x1
#define MCP4728_POWER_DOWN_NORMAL 0x0
#define MCP4728_POWER_DOWN_1K 0x1
#define MCP4728_POWER_DOWN_100K 0x2
#define MCP4728_POWER_DOWN_500K 0x3
#define MCP4728_GAIN_1 0x0
#define MCP4728_GAIN_2 0x1

void mcp4728_init(I2C_HandleTypeDef *hi2c, uint8_t address);
void mcp4728_set_channel_value(uint8_t channel, uint16_t value);
void mcp4728_set_channel_power_down(uint8_t channel, uint8_t power_down);
void mcp4728_set_channel_gain(uint8_t channel, uint8_t gain);
void mcp4728_set_channel_vref(uint8_t channel, uint8_t vref);
void mcp4728_multi_write_command();
void mcp4728_single_write_command(uint8_t channel);

#endif /* SRC_MCP4728_MCP4728_H_ */
ToPNoTCH
Inlägg: 4847
Blev medlem: 21 december 2009, 17:59:48

Re: I2C adress för MCP4728 beter sig konstigt?

Inlägg av ToPNoTCH »

Kod: Markera allt

channel_value[channel] >> 8
Nu skiftar du ut bitar ur byten igen.
Skriv svar