Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Сделать генератор псевдослучайных чисел наС
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
glebka
Необходимо сделать произвольную задержку времени на С.Если кто имеет подобный опыт, поделитесь.
Sanya Nemo
В компиряторе с Dode Vision есть функция random(); - генерирует случайные числа. В хелпе она детально описана.
glebka
Цитата(Sanya Nemo @ Oct 13 2006, 14:09) *
В компиряторе с Dode Vision есть функция random(); - генерирует случайные числа. В хелпе она детально описана.

К сожалению использую IAR, доступа к Code Vision нету, поэтому если можно поподробнее.
Семён
Тоже нет доступа к Сode Vision, может, кто подскажет, функция random(); если её поставить в самом начале программы при каждом включении будет давать один и тотже результат или разный. Просто в своё время сталкивался с подобной проблемой, что при каждом включении random генерит одно и тоже число.
singlskv
Цитата(Семён @ Oct 13 2006, 14:24) *
Тоже нет доступа к Сode Vision, может, кто подскажет, функция random(); если её поставить в самом начале программы при каждом включении будет давать один и тотже результат или разный. Просто в своё время сталкивался с подобной проблемой, что при каждом включении random генерит одно и тоже число.

Ну так это же псевдослучайные числа, так что последовательность всегда одна и таже.

В IAR и GCC функция называется rand().
Перед rand() можно вызвать srand(int initval) для установки начала последовательности.
demaven
а данные для инициализации rnd() надо брать со случайного источника, в компьютере берут время, а в контроллере? если есть что-то меняющееся независимо от контроллера, то померять и вставить
singlskv
Цитата(demaven @ Oct 13 2006, 15:59) *
а данные для инициализации rnd() надо брать со случайного источника, в компьютере берут время, а в контроллере? если есть что-то меняющееся независимо от контроллера, то померять и вставить

Если устройство питается от сети, то значение для инициализации можно брать из
АЦП меряя моментальное значение напряжения сети.
glebka
Цитата(singlskv @ Oct 13 2006, 16:12) *
Цитата(demaven @ Oct 13 2006, 15:59) *

а данные для инициализации rnd() надо брать со случайного источника, в компьютере берут время, а в контроллере? если есть что-то меняющееся независимо от контроллера, то померять и вставить

Если устройство питается от сети, то значение для инициализации можно брать из
АЦП меряя моментальное значение напряжения сети.

А если нет сети, тогда как
singlskv
Цитата(glebka @ Oct 13 2006, 16:15) *
А если нет сети, тогда как

Тогда раскажите поподробнее что есть в Вашем устройстве
Семён
Цитата(glebka @ Oct 13 2006, 16:15) *
А если нет сети, тогда как

генератор шума на стабилитроне
glebka
Цитата(Семён @ Oct 13 2006, 16:29) *
Цитата(glebka @ Oct 13 2006, 16:15) *

А если нет сети, тогда как

генератор шума на стабилитроне

у меня устройство питается от батареи,поэтому не выйдет. Плюс к одному пину подключен операционник с обвязкой.
Семён
Цитата(glebka @ Oct 13 2006, 16:35) *
у меня устройство питается от батареи,поэтому не выйдет. Плюс к одному пину подключен операционник с обвязкой.

посмотри генераторы здесь http://www.radiotexnika.ru/nzpp/
singlskv
Цитата(glebka @ Oct 13 2006, 16:35) *
у меня устройство питается от батареи,поэтому не выйдет. Плюс к одному пину подключен операционник с обвязкой.

Ну дык а что у Вас еше есть кроме батареи, AVR и операционника ?
Нет ли у Вас в устройстве случаем DC/DC преобразователя, ну или например LCD ?
Опишите поподробнее что есть в Вашем устройстве.
Alex11
Можно попробовать подвесить вход АЦП в половину питания делителем, затем измерить значение 16 или 32 раза, в зависимости от требуемой разрядности, при каждом измерении брать только младший бит результата и составить из них число для инициализации.
SasaVitebsk
Цитата(Alex11 @ Oct 13 2006, 21:40) *
Можно попробовать подвесить вход АЦП в половину питания делителем, затем измерить значение 16 или 32 раза, в зависимости от требуемой разрядности, при каждом измерении брать только младший бит результата и составить из них число для инициализации.


Да засумировать область озу неинициализированного.
defunct
Цитата(demaven @ Oct 13 2006, 14:59) *
а данные для инициализации rnd() надо брать со случайного источника, в компьютере берут время, а в контроллере? если есть что-то меняющееся независимо от контроллера, то померять и вставить

В контроллере тоже можно брать время. У вас таймеров пруд-пруди, отведите один из них под системные часы.
singlskv
Цитата(defunct @ Oct 15 2006, 06:34) *
Цитата(demaven @ Oct 13 2006, 14:59) *

а данные для инициализации rnd() надо брать со случайного источника, в компьютере берут время, а в контроллере? если есть что-то меняющееся независимо от контроллера, то померять и вставить

В контроллере тоже можно брать время. У вас таймеров пруд-пруди, отведите один из них под системные часы.

Таймером можно воспользоватся для этих целей только если в устройстве предполагается
интерактивное взаимодействие, ну например пользователь в какой-то момент жмет
кнопку, а мы измеряем время от старта устройства до нажатия на кнопку и используем
полученное время(младшую часть) как инициализацию rand(). Иначе каждый раз при старте
устройства мы будем получать одну и ту же последовательность.
Как вариант можно поставить внешний RTC и его значение использовать для инициализации rand().
glebka
Цитата(singlskv @ Oct 15 2006, 16:55) *
Цитата(defunct @ Oct 15 2006, 06:34) *

Цитата(demaven @ Oct 13 2006, 14:59) *

а данные для инициализации rnd() надо брать со случайного источника, в компьютере берут время, а в контроллере? если есть что-то меняющееся независимо от контроллера, то померять и вставить

В контроллере тоже можно брать время. У вас таймеров пруд-пруди, отведите один из них под системные часы.

Таймером можно воспользоватся для этих целей только если в устройстве предполагается
интерактивное взаимодействие, ну например пользователь в какой-то момент жмет
кнопку, а мы измеряем время от старта устройства до нажатия на кнопку и используем
полученное время(младшую часть) как инициализацию rand(). Иначе каждый раз при старте
устройства мы будем получать одну и ту же последовательность.
Как вариант можно поставить внешний RTC и его значение использовать для инициализации rand().

да ничего нету,только операционник вклученый по схеме ripper detector и батарейка.
singlskv
Цитата(glebka @ Oct 16 2006, 00:02) *
да ничего нету,только операционник вклученый по схеме ripper detector и батарейка.

Тогда можете поступить вот так, каждый раз при старте мк увеличиваете счетчик включений
Вашего устройства размещенный в EEPROM и используйте его для инициализации rand().
Будете получать при каждом включении разные последовательности псевдослучайных чисел.
demaven
Цитата(singlskv @ Oct 16 2006, 03:03) *
Цитата(glebka @ Oct 16 2006, 00:02) *

да ничего нету,только операционник вклученый по схеме ripper detector и батарейка.

Тогда можете поступить вот так, каждый раз при старте мк увеличиваете счетчик включений
Вашего устройства размещенный в EEPROM и используйте его для инициализации rand().
Будете получать при каждом включении разные последовательности псевдослучайных чисел.



самое простое и действенное решение
Demeny
Цитата(demaven @ Oct 16 2006, 07:10) *
Цитата(singlskv @ Oct 16 2006, 03:03) *

Цитата(glebka @ Oct 16 2006, 00:02) *

да ничего нету,только операционник вклученый по схеме ripper detector и батарейка.

Тогда можете поступить вот так, каждый раз при старте мк увеличиваете счетчик включений
Вашего устройства размещенный в EEPROM и используйте его для инициализации rand().
Будете получать при каждом включении разные последовательности псевдослучайных чисел.

самое простое и действенное решение

Продолжая идею, ещё лучше сохранять многобитную псевдослучайную последовательность, накопленную генератором к текущему моменту (random seed value). Идея подсмотрена в ОС Linux (/dev/random).
singlskv
Цитата(Demeny @ Oct 16 2006, 11:18) *
Цитата(demaven @ Oct 16 2006, 07:10) *

Цитата(singlskv @ Oct 16 2006, 03:03) *

Цитата(glebka @ Oct 16 2006, 00:02) *

да ничего нету,только операционник вклученый по схеме ripper detector и батарейка.

Тогда можете поступить вот так, каждый раз при старте мк увеличиваете счетчик включений
Вашего устройства размещенный в EEPROM и используйте его для инициализации rand().
Будете получать при каждом включении разные последовательности псевдослучайных чисел.

самое простое и действенное решение

Продолжая идею, ещё лучше сохранять многобитную псевдослучайную последовательность, накопленную генератором к текущему моменту (random seed value). Идея подсмотрена в ОС Linux (/dev/random).

Да, так можно делать, но только в случае когда нам заранее известен момент выключения
устройства чтобы писать в eeprom только последнее значение.
Если писать каждое значение, то мы быстро израсходуем ресурс eeprom.
Demeny
Цитата(singlskv @ Oct 16 2006, 11:46) *
Да, так можно делать, но только в случае когда нам заранее известен момент выключения
устройства чтобы писать в eeprom только последнее значение.
Если писать каждое значение, то мы быстро израсходуем ресурс eeprom.

Это можно делать и в момент включения. Вначале ставим что-то типа

Random_Seed_In_EEPROM = random (Random_Seed_In_EEPROM);

и вуаля!
singlskv
Цитата(Demeny @ Oct 16 2006, 17:19) *
Цитата(singlskv @ Oct 16 2006, 11:46) *

Да, так можно делать, но только в случае когда нам заранее известен момент выключения
устройства чтобы писать в eeprom только последнее значение.
Если писать каждое значение, то мы быстро израсходуем ресурс eeprom.

Это можно делать и в момент включения. Вначале ставим что-то типа

Random_Seed_In_EEPROM = random (Random_Seed_In_EEPROM);

и вуаля!

Это не очень хорошо.
Пусть генерируеться такая последовательность(для примера)
1 10256 387 40001 67 23070 ...
тогда при первом включении будем иметь последовательность:
1 10256 387 40001 67 23070 ...
при втором:
10256 387 40001 67 23070 ...
при третьем:
387 40001 67 23070 ...
и т.д.

То есть в итоге эти последовательности будут почти совпадать, за исключением
первых членов, что не всегда есть хорошо sad.gif
Nanobyte
Цитата(singlskv @ Oct 16 2006, 19:07) *
То есть в итоге эти последовательности будут почти совпадать, за исключением первых членов, что не всегда есть хорошо sad.gif

Достаточно будет перевернуть пару битов в прочитанном значении и последовательность будет совсем другая.
singlskv
Цитата(Nanobyte @ Oct 17 2006, 00:03) *
Цитата(singlskv @ Oct 16 2006, 19:07) *
То есть в итоге эти последовательности будут почти совпадать, за исключением первых членов, что не всегда есть хорошо sad.gif

Достаточно будет перевернуть пару битов в прочитанном значении и последовательность будет совсем другая.

Ну, фактически Вы предлагаете добавить некоторую функцию к функции rand(),
так это ни чем не будет отличаться от варианта инициализации по количеству запусков,
т.е. я добавил функцию init(N+1)=init(N)+1 , а Вы просто предлагаете добавить какую-то
другую, более сложную функцию, ну дык почему бы и нет smile.gif
В качестве варианта могу предложить например функцию построенную на числах
фибоначи init(N+2)=init(N+1)+init(N), ИМХО это должно работать красиво...
glebka
У меня каждое устройство имеет уникальный адрес записанный в EEPROM(6 байтов) и устройство постоянно включается,выключается поэтому частая запись нежелательна.
А что если использовать этот ID в таком виде:

вначале

void srand(unsigned seed), где unsigned seed моё id,

потом

int rand(void)


Вопрос к SasaVitebsk

как посчитать скока памяти осталось.
gormih
В свое время решил эту задачу так :
За начальное значение взял время ожидания нажатия пользователем первой кнопки. :-)
Правда при этом девайс должен содержать клавиатуру.
singlskv
Цитата(glebka @ Oct 17 2006, 12:23) *
У меня каждое устройство имеет уникальный адрес записанный в EEPROM(6 байтов) и устройство постоянно включается,выключается поэтому частая запись нежелательна.

На сколько часто ? Сколько раз за сутки ?
Цитата(glebka @ Oct 17 2006, 12:23) *
А что если использовать этот ID в таком виде:

вначале

void srand(unsigned seed), где unsigned seed моё id,

потом

int rand(void)

Так Вы получите каждый раз одну и ту же последовательность на данном устройстве.
На других устройствах конечно будет другая последовательность но все время постоянная.


Цитата(Михаил Горюнов @ Oct 17 2006, 13:09) *
В свое время решил эту задачу так :
За начальное значение взял время ожидания нажатия пользователем первой кнопки. :-)
Правда при этом девайс должен содержать клавиатуру.

Прежде чем давать совет, прочитайте всю ветку.
Кнопку мы уже обсуждали smile.gif
gormih
Цитата(singlskv @ Oct 17 2006, 14:08) *
Прежде чем давать совет, прочитайте всю ветку.
Кнопку мы уже обсуждали smile.gif



Прежде чем делать замечания - сами внимательно прочтите. Никто ничего подобного не предложил.
glebka
Цитата(singlskv @ Oct 17 2006, 14:08) *
Цитата(glebka @ Oct 17 2006, 12:23) *

У меня каждое устройство имеет уникальный адрес записанный в EEPROM(6 байтов) и устройство постоянно включается,выключается поэтому частая запись нежелательна.

На сколько часто ? Сколько раз за сутки ?

Я думаю где-то раз в день.

Цитата(glebka @ Oct 17 2006, 12:23) *
А что если использовать этот ID в таком виде:

вначале

void srand(unsigned seed), где unsigned seed моё id,

потом

int rand(void)

Так Вы получите каждый раз одну и ту же последовательность на данном устройстве.
На других устройствах конечно будет другая последовательность но все время постоянная.

В принципе,я так думаю что меня устроит и постоянная последовательность главное чтобы устройства не перекрывали друг друга

Цитата(Михаил Горюнов @ Oct 17 2006, 13:09) *
В свое время решил эту задачу так :
За начальное значение взял время ожидания нажатия пользователем первой кнопки. :-)
Правда при этом девайс должен содержать клавиатуру.

Прежде чем давать совет, прочитайте всю ветку.
Кнопку мы уже обсуждали smile.gif



А как засумировать область озу неинициализированного.
Сейчас роюсь в helpe для icc, может кто-нибудь сталкивался?
gormih
Зачем вообще использовать EEPROM для генератора случайных чисел?
Не проще ли привязаться к какому либо случайному событию: Время ответа какого либо внешнего устройства....
Например завести глобальную переменную

unsigned char time_rnd;

потом в месте ожидания случайного события

time_rnd++

в цикле, который обрабатывает произошедшее событие просто зафиксировать значение этой переменной.


Вот вам и случайное число...

Если не устраивает разрядность - ее легко можно увеличить.
glebka
Цитата(Михаил Горюнов @ Oct 17 2006, 14:34) *
Зачем вообще использовать EEPROM для генератора случайных чисел?
Не проще ли привязаться к какому либо случайному событию: Время ответа какого либо внешнего устройства....
Например завести глобальную переменную

unsigned char time_rnd;

потом в месте ожидания случайного события

time_rnd++

в цикле, который обрабатывает произошедшее событие просто зафиксировать значение этой переменной.


Вот вам и случайное число...

Если не устраивает разрядность - ее легко можно увеличить.


Да нет никаких событий,работающее устройство должно время от времени посылать своё ID в окружающую среду, приёмник принимает и обрабатывает.
singlskv
Цитата(Михаил Горюнов @ Oct 17 2006, 14:21) *
Цитата(singlskv @ Oct 17 2006, 14:08) *

Прежде чем давать совет, прочитайте всю ветку.
Кнопку мы уже обсуждали smile.gif



Прежде чем делать замечания - сами внимательно прочтите. Никто ничего подобного не предложил.

Пост #17
gormih
Цитата(glebka @ Oct 17 2006, 14:49) *
Да нет никаких событий,работающее устройство должно время от времени посылать своё ID в окружающую среду, приёмник принимает и обрабатывает.



А устройство содержит в себе приемопередатчик, или просто передатчик?
Если есть приемник - у них довольно часто бывает регистр уровня принимаемого сигнала - чем не источник случайных чисел... ? :-)
singlskv
Цитата(glebka @ Oct 17 2006, 14:28) *
Я думаю где-то раз в день.

раз в день это очень редко
Ресурс eeprom в современных мк 100000 записей, в старых 10000.
В худшем случае имеем 10000/365= 27 лет smile.gif
Если еще хочеться повысить надежность, то можно писать не в одну и ту же ячейку.
Например выделяем 64 байта eeprom и пишем по кругу.
Если нужны разные последовательности на разных устройствах то начальное
значение для инициализации берем Ваше ID и при каждом последующем запуске
оно увеличивается на 1.
то есть при первом запуске:
srand(ID);
writeEEPROM(ID+1);
rand();
......
rand();
при втором запуске:
srand(ID+1);
writeEEPROM(ID+2);
rand();
......
и т.д.
SasaVitebsk
Цитата(singlskv @ Oct 16 2006, 18:07) *
Цитата(Demeny @ Oct 16 2006, 17:19) *

Это можно делать и в момент включения. Вначале ставим что-то типа

Random_Seed_In_EEPROM = random (Random_Seed_In_EEPROM);

и вуаля!

Это не очень хорошо.
Пусть генерируеться такая последовательность(для примера)
1 10256 387 40001 67 23070 ...
тогда при первом включении будем иметь последовательность:
1 10256 387 40001 67 23070 ...
при втором:
10256 387 40001 67 23070 ...
при третьем:
387 40001 67 23070 ...
и т.д.

То есть в итоге эти последовательности будут почти совпадать, за исключением
первых членов, что не всегда есть хорошо sad.gif


Просто поразительно как мы пытаемся думать. smile.gif

Привсём к Вам уважении, 'singlskv' попробуйте сами разобраться (хорошенько подумав) в том что Вы написали.
1) Последоваельность не имеет значения. Мы же не сигнализацию делаем. Но даже если она имеет значение, то любыми действиями, изменяя одну последовательность мы приходим к другой. Тоже жёско забитой. это ПСЕВДОСЛУЧАЙНЫЕ числа! Надо это понимать.
2) Объём последовательности - мощность генератора - определяется практически только ФУКЦИЕЙ (формулой) генератора псевдослучайных чисел. В рассматриваемом вопросе - это функция Си компилятора IAR. Если хотите этого избежать возьмите справочник, выберите тип распределения и напишите функцию сами.
3) Пытаясь инициализировать функцию Вы хотите получить уже случайное число. Так зачем функция? Потому, что Вы не совсем доверяете? Или Вас не устраивает мощность такого генератора?

Подытоживая, - этот спор ни о чём. Выводы:
1) Объём выборки определяется только функцией. Например ф-ия X(i+1) = FRAC(11*X(i)+Pi) даёт 8000 неповторяющихся значений, а X(i+1) = FRAC(x(i)/z(i)+Pi), где Z(i+1)=Z(i)+1*10**-8. даёт 8,9*10**7 чисел.
2) Инициализацией всё равно не увеличить мощность формулы. Поэтому любой из предложенных методов является действенным. К ним я отношу.

1) Если есть, использование серийного номера или формулы с ним связанной.
2) Использование различных внешних элементов. АЦП, RC и т.д.
3) Использование формулы связаной с неинициализируемым ОЗУ.
4) Измерение WDT.
И т.п.

Определить что лучше что хуже на пальцах не удастся, так как это статистика. Надо определить мощность генерации случайного числа, этими способами на большом количестве изделий. Спор на "понятиях" - бессмысленен.

Использование в качестве инициализирующего значения самого числа генерируемого RND не поможет. Так как речь идёт о ПЕРВОНАЧАЛЬНОМ запуске. То есть запустили партию изделий - и что? В таком случае надо сразу зашивать что-то. Тогда всё тип топ. Но это тот же первый пункт!
singlskv
Цитата(SasaVitebsk @ Oct 17 2006, 15:54) *
1) Последоваельность не имеет значения. Мы же не сигнализацию делаем. Но даже если она имеет значение, то любыми действиями, изменяя одну последовательность мы приходим к другой. Тоже жёско забитой. это ПСЕВДОСЛУЧАЙНЫЕ числа! Надо это понимать.

Замечу, что в своих постах я неоднакратно подчеркивал что
последовательность псевдослучайная smile.gif
Цитата
2) Объём последовательности - мощность генератора - определяется практически только ФУКЦИЕЙ (формулой) генератора псевдослучайных чисел. В рассматриваемом вопросе - это функция Си компилятора IAR. Если хотите этого избежать возьмите справочник, выберите тип распределения и напишите функцию сами.

Вот здесь я с Вами согласен
Цитата
3) Пытаясь инициализировать функцию Вы хотите получить уже случайное число. Так зачем функция? Потому, что Вы не совсем доверяете? Или Вас не устраивает мощность такого генератора?

Не пытаюсь получить абсолютно случайное, а пытаюсь сделать так чтобы при каждом
новом старте устройства, последовательность начиналась с разных мест.
Цитата
2) Инициализацией всё равно не увеличить мощность формулы. Поэтому любой из предложенных методов является действенным.

Мощность не увеличит, а вот разные последовательности получить можно.
Пример:
Пусть у нас есть некий генератор с диапазоном 1 - 100
Пусть при подстановке стартового значения 1 мы получим следующую последовательность:
1 78 36 49 84 8 23 58 63 94 1 78 ........ и далее зациклились
А при стартовом значении 2 :
2 91 47 5 53 17 72 25 88 39 2 91 ........
генератор один - мощность одна, а значения разные smile.gif
Цитата
Использование в качестве инициализирующего значения самого числа генерируемого RND не поможет. Так как речь идёт о ПЕРВОНАЧАЛЬНОМ запуске. То есть запустили партию изделий - и что? В таком случае надо сразу зашивать что-то. Тогда всё тип топ. Но это тот же первый пункт!

Ну дык для первоначального запуска у автора топика есть оригинальные ID
singlskv
Цитата(glebka @ Oct 17 2006, 12:23) *
У меня каждое устройство имеет уникальный адрес записанный в EEPROM(6 байтов) и устройство постоянно включается,выключается поэтому частая запись нежелательна.

Цитата(glebka @ Oct 17 2006, 12:23) *
А что если использовать этот ID в таком виде:

вначале

void srand(unsigned seed), где unsigned seed моё id,

потом

int rand(void)

Цитата
В принципе,я так думаю что меня устроит и постоянная последовательность главное чтобы устройства не перекрывали друг друга

Ну тогда так и делайте
srand(ID)
rand()
........
rand()

Просто в начальном посте не было понятно что же Вам нужно в итоге... smile.gif

Цитата
Да нет никаких событий,работающее устройство должно время от времени посылать своё ID в окружающую среду, приёмник принимает и обрабатывает.

То есть Вам нужно разделение одного радиоканала на много независимых передатчиков.
Тогда можно обойтись вообще без случайных чисел.
Пусть есть 10 независимых передатчиков. У каждого из них в младшей части ID записан
номер от 1 до 10.
Выбираем довольно большое число (по сравнению с количеством передатчиков)
например 1000. Для каждого передатчика время между посылками делаем пропорционально
его номеру + наша константа: T=(1000+K)N где N>двухкратного времени одиночной посылки.
Иногда конечно будут возникать коллизии, но очень не часто.

Если хочеться еще уменьшить количество коллизий, тогда нужно смотреть в сторону простых чисел.
Пусть есть 10 передатчиков.
Выбираем 10 первых простых чисел больше 1000 и прописываем их в ID.
Для каждого передатчика время между посылками делаем пропорционально этим простым
числам. коллизий будет очень мало.
demaven
8 передатчиков работали на одной частоте на 64 приемника, по 8 приемников на каждый передатчик и приемники каждый обрабатывал только тот сигнал, который им предназначался, коллизии были, без них низзя, но при 3 кратном повторе передачи ВСЕГДА информация принималась правильно, использовались простые числа практически из самого начала, 5, 7, 9, 11, 13 и т.д.
glebka
[quote]
Просто в начальном посте не было понятно что же Вам нужно в итоге... smile.gif

Прошу прощения,техническое задание корректировалось на ходу.

Пока сделал ,по варианту

srand(ID);
while(1)
{
srand(ID)
rand()
........
srand(ID++);
rand();
}

Делает вид что работает.Идея в принципе правильная,без наворотов.

Спасибо за предложенные идеи,может где ещё пригодятся.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.