Цифровой потенциометр MCP 41010

VictorArx

★★★✩✩✩✩
22 Мар 2021
636
102
Доброго времени суток. Подскажите в чём проблема. Имеется цифровой потенциометр и код к нему. В мониторе порта всё отображается , как с потециометром, так и без него. Или потенциометр неисправный или я чего то не дотумкал.
C++:
#include <SPI.h>                            // инклюдим библиотеку для аппаратного SPI

#define CS 10                               // нога чипслекет       

byte val = 0;
 
void setup() {
  Serial.begin(115200);
  SPI.begin();   

  pinMode (CS, OUTPUT);   


}
 
void loop() {
 
    float voltage = (analogRead(A0) * 5.0)/ 1024.0;  // читаем напряжение на входе А0
    Serial.print("voltage = " );                // отправляем данные о напряжении в монитор порта     
    Serial.print(voltage);     
    Serial.print("  val = ");                   // значение которое пишем в потенциометр
    Serial.print(val, BIN);                     // бинарное
    Serial.print(" / ");
    Serial.println(val, DEC);                   // десятичное

    val++;                                      // прибавляем к переменной 1
    MCP4xxxxWrite(val);                         // пишем значение переменной в потенциометр

    delay(50);                                 // ждем до следующего раза
 
}
 
void MCP4xxxxWrite(byte val) {              // отправляет в потенциометр значение ползунка
 
    
    digitalWrite(CS, LOW);                    // включаем прием данных микросхемой
    SPI.transfer(0b0010001);                 // отправляем первый байт в регистр конфигурации
    SPI.transfer(val);                        // отправляем второй байт в "регистр ползунка"
        
  digitalWrite(CS, HIGH);
    
    
                    // выключаем прием данных микросхемой
}
 

EugeneFrol

✩✩✩✩✩✩✩
17 Апр 2024
48
6
50
Ну а сам MCP41010 выходное сопротивление меняет?
В коде только запись в SPI и всё. Нет контроля связи.
Однако если MCP41010 подключен, то обе команды возвращают 0.
Т.е.:
ret1 = SPI.tranfer(0b0010001);
ret2 = SPI.tranfer(val);
if(ret1 != 0 || ret2 != 0) Serial.print("Нет связи с MCP41010!");
 

VictorArx

★★★✩✩✩✩
22 Мар 2021
636
102
Монитор порта показывает значение от 0 до 255 и по новой от 0 до 255 и т.д. без потенциометра. Какую роль тогда играет потенциометр?
 

VictorArx

★★★✩✩✩✩
22 Мар 2021
636
102
С потенциометром MCP 41010 разобрался, не было контакта в микросхеме. Теперь подключил X9C103. Написал код( часть из инета, и свой добавил, чтобы отображалось в мониторе порта). В чём проблема. Увеличивает сопротивление от 0 до 1023 в мониторе порта, а обратно не уменьшае плавно, а сразу скидывает в 0 и сразу снова начинает увеличивать сопротивление.Другими словами не уменьшает плавно с 1023 до 0. То ли потенциометр бракованый то ли в коде ошибка. Помогите уважаемые программисты разобраться.


C++:
const int CS = 4;
const int INC = 3;
const int UD = 2;

const int pot = A0;
const int led = 5;
int val = 0;


void setup() {

   Serial.begin(9600); // Запускаем монитор порта со скоростью 9600 бод
  pinMode(pot, INPUT);
  pinMode(led, OUTPUT);

  pinMode(CS, OUTPUT);
  pinMode(INC, OUTPUT);
  pinMode(UD, OUTPUT);



}

void loop() {
   for (int i=0; i<=100; i+=10) {
    setResistance(i);
    delay(100);
  }
}

// Задаёт сопротивление на "подвижном" выводе.
// Уровень percent - от 0 до 100% от максимума.
void setResistance(int percent) {
  // Понижаем сопротивление до 0%:
  digitalWrite(UD, HIGH); // выбираем понижение
  digitalWrite(CS, LOW); // выбираем потенциометр X9C
  for (int i=0; i<100; i++) { // т.к. потенциометр имеет 100 доступных позиций
    digitalWrite(INC, LOW);
    delayMicroseconds(1);
    digitalWrite(INC, HIGH);
    delayMicroseconds(1);


  }

  // Поднимаем сопротивление до нужного:
  digitalWrite(UD, LOW);
  for (int i=100; i>percent; i--) {
    digitalWrite(INC, LOW);
    delayMicroseconds(1);
    digitalWrite(INC, HIGH);
    delayMicroseconds(1);

  int val = analogRead(pot); // Считываем аналоговое значение с пина A0 (от 0 до 1023)
  Serial.println(val); // Выводим считанное значение в монитор порта
  delay(500); // Небольшая

  analogWrite(led, val);

  }

  digitalWrite(CS, HIGH); /* запоминаем значение
  и выходим из режима настройки */
}
 
Изменено:

poty

★★★★★★★
19 Фев 2020
3,557
1,015

@VictorArx, это два цикла, обеспечивающие установку переданного в функцию значения. А значение передаётся лишь в возрастающем цикле.
Ну, и тайминги нужно соблюдать.
 

VictorArx

★★★✩✩✩✩
22 Мар 2021
636
102
@poty, по ходу у цифровых потенциометров плавное увеличение сопротивления только в одну сторону, затем в исходное состояние и снова нарастание.
 

Вложения

viktor1703

★★★✩✩✩✩
9 Дек 2021
771
190
@VictorArx, пройдитесь по коду так, как его выполняет микроконтроллер, строка за строкой, а не так как кажется выполнение кода вам. И вы поймёте где ваша ошибка.
C++:
void setResistance(int percent) {
  // Понижаем сопротивление до 0%:
  digitalWrite(UD, HIGH); // выбираем понижение
  digitalWrite(CS, LOW); // выбираем потенциометр X9C
  for (int i=0; i<100; i++) { // т.к. потенциометр имеет 100 доступных позиций
    digitalWrite(INC, LOW);
    delayMicroseconds(1);
    digitalWrite(INC, HIGH);
    delayMicroseconds(1);


  }

  // Поднимаем сопротивление до нужного:
  digitalWrite(UD, LOW);
  for (int i=0; i<percent; i++) {
    digitalWrite(INC, LOW);
    delayMicroseconds(1);
    digitalWrite(INC, HIGH);
    delayMicroseconds(1);

  int val = analogRead(pot); // Считываем аналоговое значение с пина A0 (от 0 до 1023)
  Serial.println(val); // Выводим считанное значение в монитор порта
  delay(500); // Небольшая

  analogWrite(led, val);

  }

  digitalWrite(CS, HIGH); /* запоминаем значение
  и выходим из режима настройки */
}
Начинается функция setResistance.
Первый цикл: понижаем сопротивление до 0.
Устанавливаете пин UD;
Сбрасываете пин CS;
Выполняется цикл, в котором
от 0 до 100
{
дергаете ногой INC. //допустим, происходит понижение сопротивления.
}
Цикл закончился.
Затем вы начинаете повышать сопротивление. Второй цикл.
Сбрасываете пин UD.
Выполняется цикл, в котором
от 0 до percent (я не знаю сколько это, в приведенном вами коде этого нет, но допустим, что где-то прописано, что percent =100)
{
дергаете пин INC;
Читаете значение на пине А0;
Выводите это значение в Serial;
Задержка (полсекунды);
Установка в ШИМ значения с А0; //Видимо, не верите сериалу, еще и визуально хотите контролировать изменение сопротивления.
}
Цикл закончился.
Устанавливаете пин CS;
И завершается функция setResistance.
Правильно, так все работает? По вашему плану?
Внимание вопрос: почему же вы ждете, что сериал вам будет выдавать значения плавного понижения сопротивления? В каком месте вы это ему поручили?
 
Изменено:

VictorArx

★★★✩✩✩✩
22 Мар 2021
636
102
@viktor1703, этот код я скачал в инете, по причине не очень разбираюсь в программировании от слова совсем. Декремент тоже подставлял ,тоже не получилось. В теории вы всё правильно описали. Только не пойму где ошибка.
 

VictorArx

★★★✩✩✩✩
22 Мар 2021
636
102
Тогда нужно изучать.
Так изучаю, только вы начали со школьной скамьи, а я уже в преклонном возрасте, улавливаете разницу.
for (int i=100; i>=0; i--); здесь тоже поручал.Был бы очень вам признателен, если вместо теории , подправить на практике, если конечно не затруднит. Спасибо.
 
Изменено:

viktor1703

★★★✩✩✩✩
9 Дек 2021
771
190
Хоть так
for (int i=100; i>=0; i--);
Хоть так
for (int i=0; i<100; i++)
микроконтроллеру не важно в какую сторону считать, а микросхеме сопротивлений вообще фиолетово, что кто и как считает. Сопротивление она скорее всего меняет и "вверх" и "вниз", только вы не опрашиваете пин при понижении сопротивления и не видите меняется ли оно, а только при повышении. Вставьте кусок кода с опросом и выводом значений
C++:
int val = analogRead(pot); // Считываем аналоговое значение с пина A0 (от 0 до 1023)
  Serial.println(val); // Выводим считанное значение в монитор порта
  delay(500); // Небольшая

  analogWrite(led, val);
в первый цикл
 

VictorArx

★★★✩✩✩✩
22 Мар 2021
636
102
Так всё так и делаю, подозреваю, что микросхема бракованная. Заказал в DIP корпусе. В потенциометре MCP41010 по протоколу SPI всё чётко работает и в мониторе порта видно дискретное увеличение и уменьшение значений. Здесь перепробовал практически всё, несколько кодов. Результат один. Может принцип его такой.
 
Изменено:

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,482
991
59
Марий-Эл
1763883204965.png
Это внутренняя структура 42ххх
У 41ххх такая же. По ней видно, что можно считать только то, что записано в сдвиговом регистре, а не в каком состоянии реально находится резистор.
Все потуги считать состояние ни к чему хорошему не приведут.
Нужно мерять состояние выходов и доке указано как.
1763883516300.png
1763883551263.png
41ххх одноканальный. Ему нужно закидывать число 0-255 для увеличения и 255-0 для уменьшения.
Для этого даже библиотеки не нужны.
 

poty

★★★★★★★
19 Фев 2020
3,557
1,015
@VictorArx, ничего подобного. Добавьте в loop цикл уменьшения percent и всё будет ОК.
 

VictorArx

★★★✩✩✩✩
22 Мар 2021
636
102
@VictorArx, ничего подобного. Добавьте в loop цикл уменьшения percent и всё будет ОК.
Так пробовал декремент, не уменьшает плавно, доходит от 0 до 1023, потом сразу в 0 и снова дискретно до 1023. Скорее брак, пробовал разные коды из инета.

@Эдуард Анисимов, с потенциометром MCP 41010 всё в порядке и увеличивает и уменьшает дискретно. Мудохаюсь с X9C103.
 

r4wabr

★✩✩✩✩✩✩
21 Май 2019
72
17
42
Ижевск
Даташиты никто не читает походу. Напиши для прямого и обратного хода отдельные процедуры согласно таблицы и их в цикле крути.

C++:
void wiperUp(void) {
  digitalWrite(CS,HIGH);
  digitalWrite(UD,HIGH);
  delay(1);
  digitalWrite(INC,HIGH);
  delay(1);
  digitalWrite(CS,LOW);
  delay(1);
  digitalWrite(INC,LOW);
  delay(1);
  digitalWrite(INC,HIGH);
  delay(1);
  digitalWrite(CS,HIGH);

}


void wiperDown(void) {
  digitalWrite(CS,HIGH); 
  digitalWrite(UD,LOW);
  delay(1);
  digitalWrite(INC,HIGH);
  delay(1);
  digitalWrite(CS,LOW);
  delay(1);
  digitalWrite(INC,LOW);
  delay(1);
  digitalWrite(INC,HIGH);
  delay(1);
  digitalWrite(CS,HIGH);

}
 

Вложения

Изменено:

VictorArx

★★★✩✩✩✩
22 Мар 2021
636
102
@bort707, вы невнимательны, я в коде делал инкремент и декремент
for (int i=0; i<100; i++)
for (int i=100; i>percent; i--) ничего не меняется.
 

r4wabr

★✩✩✩✩✩✩
21 Май 2019
72
17
42
Ижевск
В исходном состоянии выходной пин имеет лог 0 на выходе, а не единицу. Дальше объяснять.?
Я 2 функции выложил. Пробуйте.
 

VictorArx

★★★✩✩✩✩
22 Мар 2021
636
102
@r4wabr, даташит читал, крутилки делал, если некоторые юмора не понимают, их проблемы. Заказал ещё микросхемы в DIP корпусе.
 

r4wabr

★✩✩✩✩✩✩
21 Май 2019
72
17
42
Ижевск
@r4wabr, даташит читал, крутилки делал, если некоторые юмора не понимают, их проблемы. Заказал ещё микросхемы в DIP корпусе.
C++:
void wiperUp(void) {
  digitalWrite(CS,HIGH);
  digitalWrite(UD,HIGH);
  delay(1);
  digitalWrite(INC,HIGH);
  delay(1);
  digitalWrite(CS,LOW);
  delay(1);
  digitalWrite(INC,LOW);
  delay(1);
  digitalWrite(INC,HIGH);
  delay(1);
  digitalWrite(CS,HIGH);

}


void wiperDown(void) {
  digitalWrite(CS,HIGH);
  digitalWrite(UD,LOW);
  delay(1);
  digitalWrite(INC,HIGH);
  delay(1);
  digitalWrite(CS,LOW);
  delay(1);
  digitalWrite(INC,LOW);
  delay(1);
  digitalWrite(INC,HIGH);
  delay(1);
  digitalWrite(CS,HIGH);

}